package vnet.sms.gateway.server.framework; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import javax.jms.ObjectMessage; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.local.DefaultLocalServerChannelFactory; import org.jboss.netty.channel.local.LocalAddress; import org.junit.Test; import org.springframework.jms.core.JmsTemplate; import org.springframework.security.authentication.AuthenticationManager; import vnet.sms.common.messages.PingRequest; import vnet.sms.common.messages.PingResponse; import vnet.sms.gateway.server.framework.internal.channel.GatewayServerChannelPipelineFactory; import vnet.sms.gateway.server.framework.spi.GatewayServerDescription; import vnet.sms.gateway.server.framework.test.AcceptAllAuthenticationManager; import vnet.sms.gateway.server.framework.test.DenyAllAuthenticationManager; import vnet.sms.gateway.server.framework.test.LocalClient; import vnet.sms.gateway.transports.serialization.ReferenceableMessageContainer; public class PingTest extends AbstractGatewayServerTest { @Test public final void assertThatGatewayServerSendsFirstPingRequestToClientAfterPingIntervalHasElapsed() throws Throwable { final LocalAddress serverAddress = new LocalAddress("test:server:7"); final int availableIncomingWindows = 1000; final long incomingWindowWaitTimeMillis = 1L; final long failedLoginResponseMillis = 100L; final int pingIntervalSeconds = 1; final long pingResponseTimeoutMillis = 200000L; final AuthenticationManager authenticationManager = new AcceptAllAuthenticationManager(); final JmsTemplate jmsTemplate = newJmsTemplate(); final GatewayServerChannelPipelineFactory<Integer, ReferenceableMessageContainer> channelPipelineFactory = newGatewayServerChannelPipelineFactory( "assertThatGatewayServerSendsFirstPingRequestToClientAfterPingIntervalHasElapsed", availableIncomingWindows, incomingWindowWaitTimeMillis, failedLoginResponseMillis, pingIntervalSeconds, pingResponseTimeoutMillis, authenticationManager, jmsTemplate); final GatewayServer<Integer, ReferenceableMessageContainer> objectUnderTest = new GatewayServer<Integer, ReferenceableMessageContainer>( new TestGatewayServerDescription(), "assertThatGatewayServerRespondsWithAFailedLoginResponseToAFailedLoginRequest", serverAddress, new DefaultLocalServerChannelFactory(), channelPipelineFactory); objectUnderTest.start(); final CountDownLatch pingReceived = new CountDownLatch(1); final LocalClient.MessageListener waitForPing = new LocalClient.MessageListener() { @Override public void messageReceived(final MessageEvent e) { if (ReferenceableMessageContainer.class.cast(e.getMessage()) .getMessage() instanceof PingRequest) { pingReceived.countDown(); } } }; final LocalClient client = new LocalClient(serverAddress); client.connect(); // Should start ping timeout client.login( 1, "assertThatGatewayServerContinuesSendingPingRequestsAfterReceivingPingResponse", "whatever"); client.listen(waitForPing); assertTrue("Expected to receive Ping after ping interval of " + pingIntervalSeconds + " seconds had expired", pingReceived.await(pingIntervalSeconds * 1000 + 100, TimeUnit.MILLISECONDS)); client.disconnect(); objectUnderTest.stop(); } @SuppressWarnings("serial") private static final class TestGatewayServerDescription extends GatewayServerDescription { public TestGatewayServerDescription() { super("Test", 1, 0, 0, "BETA", "15"); } } @Test public final void assertThatGatewayServerContinuesSendingPingRequestsAfterReceivingPingResponse() throws Throwable { final LocalAddress serverAddress = new LocalAddress("test:server:8"); final int availableIncomingWindows = 1000; final long incomingWindowWaitTimeMillis = 1L; final long failedLoginResponseMillis = 100L; final int pingIntervalSeconds = 1; final long pingResponseTimeoutMillis = 200000L; final AuthenticationManager authenticationManager = new AcceptAllAuthenticationManager(); final JmsTemplate jmsTemplate = newJmsTemplate(); final GatewayServerChannelPipelineFactory<Integer, ReferenceableMessageContainer> channelPipelineFactory = newGatewayServerChannelPipelineFactory( "assertThatGatewayServerContinuesSendingPingRequestsAfterReceivingPingResponse", availableIncomingWindows, incomingWindowWaitTimeMillis, failedLoginResponseMillis, pingIntervalSeconds, pingResponseTimeoutMillis, authenticationManager, jmsTemplate); final GatewayServer<Integer, ReferenceableMessageContainer> objectUnderTest = new GatewayServer<Integer, ReferenceableMessageContainer>( new TestGatewayServerDescription(), "assertThatGatewayServerRespondsWithAFailedLoginResponseToAFailedLoginRequest", serverAddress, new DefaultLocalServerChannelFactory(), channelPipelineFactory); objectUnderTest.start(); final LocalClient client = new LocalClient(serverAddress); // Should start ping timeout client.connect(); // Login. Otherwise, our LoginResponse will be discarded client.login( 1, "assertThatGatewayServerContinuesSendingPingRequestsAfterReceivingPingResponse", "whatever"); final CountDownLatch firstPingReceived = new CountDownLatch(1); final AtomicReference<PingRequest> firstReceivedPing = new AtomicReference<PingRequest>(); final LocalClient.MessageListener waitForFirstPing = new LocalClient.MessageListener() { @Override public void messageReceived(final MessageEvent e) { if (ReferenceableMessageContainer.class.cast(e.getMessage()) .getMessage() instanceof PingRequest) { firstReceivedPing .set((PingRequest) ReferenceableMessageContainer.class .cast(e.getMessage()).getMessage()); firstPingReceived.countDown(); } } }; client.listen(waitForFirstPing); assertTrue("Expected to receive Ping after ping interval of " + pingIntervalSeconds + " seconds had expired", firstPingReceived.await(pingIntervalSeconds * 1000 + 100, TimeUnit.MILLISECONDS)); final CountDownLatch secondPingReceived = new CountDownLatch(1); final LocalClient.MessageListener waitForSecondPing = new LocalClient.MessageListener() { @Override public void messageReceived(final MessageEvent e) { if (ReferenceableMessageContainer.class.cast(e.getMessage()) .getMessage() instanceof PingRequest) { secondPingReceived.countDown(); } } }; client.listen(waitForSecondPing); final PingResponse responseToFirstPingRequest = PingResponse .accept(firstReceivedPing.get()); client.sendMessage(2, responseToFirstPingRequest); assertTrue( "Expected to receive second Ping after sending PingResponse and aiting for " + pingIntervalSeconds + " seconds", secondPingReceived.await(pingIntervalSeconds * 1000 + 100, TimeUnit.MILLISECONDS)); client.disconnect(); objectUnderTest.stop(); } @Test public final void assertThatGatewayServerDoesNotForwardPingRequestToJmsServer() throws Throwable { final int messageReference = 1; final LocalAddress serverAddress = new LocalAddress("test:server:9"); final int availableIncomingWindows = 10; final long incomingWindowWaitTimeMillis = 1000L; final long failedLoginResponseMillis = 1000L; final int pingIntervalSeconds = 100; final long pingResponseTimeoutMillis = 2000L; final AuthenticationManager authenticationManager = new DenyAllAuthenticationManager(); final JmsTemplate jmsTemplate = newJmsTemplate(); final GatewayServerChannelPipelineFactory<Integer, ReferenceableMessageContainer> channelPipelineFactory = newGatewayServerChannelPipelineFactory( "assertThatGatewayServerDoesNotForwardPingRequestToJmsServer", availableIncomingWindows, incomingWindowWaitTimeMillis, failedLoginResponseMillis, pingIntervalSeconds, pingResponseTimeoutMillis, authenticationManager, jmsTemplate); final GatewayServer<Integer, ReferenceableMessageContainer> objectUnderTest = new GatewayServer<Integer, ReferenceableMessageContainer>( new TestGatewayServerDescription(), "assertThatGatewayServerForwardsFailedLoginRequestToJmsServer", serverAddress, new DefaultLocalServerChannelFactory(), channelPipelineFactory); objectUnderTest.start(); final PingRequest pingRequest = new PingRequest(); final LocalClient client = new LocalClient(serverAddress); client.connect(); client.sendMessage(messageReference, pingRequest); client.disconnect(); final ObjectMessage forwardedMessage = (ObjectMessage) jmsTemplate .receive(); objectUnderTest.stop(); assertNull( "GatewayServer should NOT have forwarded PingRequest passed in to JMS server, yet it did", forwardedMessage); } }