/** * */ package vnet.routing.netty.server.support.ping; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.group.ChannelGroupFuture; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.handler.codec.string.StringDecoder; import org.jboss.netty.handler.codec.string.StringEncoder; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import vnet.routing.netty.server.support.test.EchoServerHandler; import vnet.routing.netty.server.support.test.EchoTestClient; import vnet.routing.netty.server.support.test.ResponseListener; /** * @author obergner * */ public class PingServiceIT { private static final int ECHO_SERVER_PORT = 12345; private static final ChannelGroup PING_CHANNELS = new DefaultChannelGroup( "Ping Channels - " + PingServiceIT.class.getName()); private static final TestEchoServer ECHO_SERVER = new TestEchoServer( PING_CHANNELS); @BeforeClass public static void startEchoServer() { ECHO_SERVER.start(); } @AfterClass public static void stopEchoServer() { ECHO_SERVER.stop(); } private final EchoTestClient echoClient = new EchoTestClient("localhost", ECHO_SERVER_PORT); private final PingService<String> objectUnderTest = new PingService<String>( PING_CHANNELS, new PingFactory<String>() { @Override public String newPing() { return "PING"; } }, Executors.newScheduledThreadPool(1), 1); @Before public void startEchoClient() throws Exception { this.echoClient.start(); } @After public void stopPingService() { this.objectUnderTest.stop(); } @After public void stopEchoClient() throws Exception { this.echoClient.stop(); } /** * Test method for * {@link vnet.routing.netty.server.support.ping.PingService#start()}. * * @throws Exception */ @Test(timeout = 20000) public final void assertThatStartSendsPingOverChannel() throws Exception { final CountDownLatch threePingsReceived = new CountDownLatch(3); final ResponseListener pingListener = new ResponseListener() { @Override public void responseReceived(final String response) { if (response.equals("PING")) { threePingsReceived.countDown(); } } }; this.echoClient.sendRequest("DUMMY", pingListener); this.objectUnderTest.start(); threePingsReceived.await(); } /** * Test method for * {@link vnet.routing.netty.server.support.ping.PingService#pause()}. * * @throws Exception */ @Test(timeout = 20000) public final void assertThatPauseStopsPingSender() throws Exception { final CountDownLatch twoPingsReceived = new CountDownLatch(2); final ResponseListener pingListener = new ResponseListener() { @Override public void responseReceived(final String response) { if (response.equals("PING")) { twoPingsReceived.countDown(); } } }; this.echoClient.sendRequest("DUMMY", pingListener); this.objectUnderTest.start(); twoPingsReceived.await(); this.objectUnderTest.pause(); final CountDownLatch anyPingReceived = new CountDownLatch(1); final ResponseListener pingErrorListener = new ResponseListener() { @Override public void responseReceived(final String response) { if (response.equals("PING")) { anyPingReceived.countDown(); } } }; this.echoClient.sendRequest("PAUSE", pingErrorListener); assertFalse("pause() did not stop ping", anyPingReceived.await(2, TimeUnit.SECONDS)); } /** * Test method for * {@link vnet.routing.netty.server.support.ping.PingService#reschedule(int)} * . * * @throws Exception */ @Test(timeout = 20000) public final void assertThatRescheduleAltersPingInterval() throws Exception { final CountDownLatch twoPingsReceived = new CountDownLatch(2); final ResponseListener pingListener = new ResponseListener() { @Override public void responseReceived(final String response) { if (response.equals("PING")) { twoPingsReceived.countDown(); } } }; this.echoClient.sendRequest("DUMMY", pingListener); this.objectUnderTest.start(); twoPingsReceived.await(); final int newPingIntervalSeconds = 3; this.objectUnderTest.reschedule(newPingIntervalSeconds); final CountDownLatch twoPingsAfterRescheduleReceived = new CountDownLatch( 2); final List<Long> pingTimes = new ArrayList<Long>(2); final ResponseListener pingRescheduledListener = new ResponseListener() { @Override public void responseReceived(final String response) { if (response.equals("PING")) { pingTimes.add(System.currentTimeMillis()); twoPingsAfterRescheduleReceived.countDown(); } } }; this.echoClient.sendRequest("RESCHEDULED", pingRescheduledListener); twoPingsAfterRescheduleReceived.await(); final long intervalMillis = pingTimes.get(1) - pingTimes.get(0); assertTrue("reschedule(" + newPingIntervalSeconds + ") did not alter ping interval", intervalMillis > (newPingIntervalSeconds * 1000L - 300L)); } /** * Test method for * {@link vnet.routing.netty.server.support.ping.PingService#stop()}. * * @throws Exception */ @Test(timeout = 20000) public final void assertThatStopDoesStopPingSender() throws Exception { final CountDownLatch twoPingsReceived = new CountDownLatch(2); final ResponseListener pingListener = new ResponseListener() { @Override public void responseReceived(final String response) { if (response.equals("PING")) { twoPingsReceived.countDown(); } } }; this.echoClient.sendRequest("DUMMY", pingListener); this.objectUnderTest.start(); twoPingsReceived.await(); this.objectUnderTest.stop(); final CountDownLatch anyPingReceived = new CountDownLatch(1); final ResponseListener pingErrorListener = new ResponseListener() { @Override public void responseReceived(final String response) { if (response.equals("PING")) { anyPingReceived.countDown(); } } }; this.echoClient.sendRequest("STOP", pingErrorListener); assertFalse("stop() did not stop ping", anyPingReceived.await(2, TimeUnit.SECONDS)); } private static class TestEchoServer { private final ChannelGroup pingChannels; private ServerBootstrap bootstrap; TestEchoServer(final ChannelGroup pingChannels) { this.pingChannels = pingChannels; } void start() { this.bootstrap = new ServerBootstrap( new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); this.bootstrap.setPipelineFactory(new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline(new StringEncoder(), new StringDecoder(), new EchoServerHandler( TestEchoServer.this.pingChannels)); } }); final Channel serverSocketChannel = this.bootstrap .bind(new InetSocketAddress(ECHO_SERVER_PORT)); this.pingChannels.add(serverSocketChannel); } void stop() { final ChannelGroupFuture close = this.pingChannels.close(); close.awaitUninterruptibly(); this.bootstrap.releaseExternalResources(); } } }