Search in sources :

Example 21 with ConditionCheck

use of com.linkedin.databus2.test.ConditionCheck in project databus by linkedin.

the class TestHttpResponseProcessor method testReadTimeoutChunking.

@Test
public void testReadTimeoutChunking() throws DatabusException {
    final Logger log = Logger.getLogger("GenericHttpResponseHandler.testReadTimeoutChunking");
    log.info("start");
    final GenericHttpResponseHandler responseHandler = new GenericHttpResponseHandler(KeepAliveType.KEEP_ALIVE);
    responseHandler.getLog().setLevel(_logLevel);
    TestHttpResponseProcessor respProcessor = new TestHttpResponseProcessor(log);
    TestConnectListener connectListener = new TestConnectListener(log);
    TestSendRequestListener requestListener = new TestSendRequestListener(log);
    TestCloseListener closeListener = new TestCloseListener(log);
    responseHandler.setConnectionListener(connectListener);
    Channel channel = createClientBootstrap(responseHandler);
    SocketAddress clientAddr = channel.getLocalAddress();
    try {
        setListeners(responseHandler, respProcessor, requestListener, closeListener);
        channel.write(new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/test"));
        //It seems that there is a race condition between the writeFuture succeeding
        //and the writeComplete message getting to the handler. Make sure that the
        //writeComplete has got to the handler before we do anything else with
        //the channel.
        final GenericHttpResponseHandler handler = getResponseHandler(channel);
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                return handler._messageState.hasSentRequest();
            }
        }, "request sent", 1000, log);
        HttpResponse resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        resp.setHeader(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED);
        sendServerResponse(clientAddr, resp, 1000);
        HttpChunk chunk1 = new DefaultHttpChunk(ChannelBuffers.wrappedBuffer("chunk1".getBytes(Charset.defaultCharset())));
        sendServerResponse(clientAddr, chunk1, 1000);
        final List<String> callbacks = respProcessor.getCallbacks();
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                return 2 == callbacks.size();
            }
        }, "waiting for response processed", 1000, null);
        Assert.assertEquals(callbacks.get(0), "startResponse");
        Assert.assertEquals(callbacks.get(1), "addChunk");
        Channels.fireExceptionCaught(channel, new ReadTimeoutException());
        channel.close();
        final List<String> closeCallbacks = closeListener.getCallbacks();
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                return 3 == callbacks.size() && 1 == closeCallbacks.size();
            }
        }, "waiting for response processed", 1000, null);
        final List<String> connectCallbacks = connectListener.getCallbacks();
        final List<String> requestCallbacks = requestListener.getCallbacks();
        Assert.assertEquals(callbacks.get(0), "startResponse");
        Assert.assertEquals(callbacks.get(1), "addChunk");
        Assert.assertTrue(callbacks.get(2).startsWith("channelException"));
        //Assert.assertEquals(callbacks.get(3), "channelClosed"); // no more channelClosed after channel Exception
        //make sure that no new callbacks have showed up
        stateSanityCheck(connectCallbacks, requestCallbacks, callbacks, closeCallbacks);
        Assert.assertEquals(callbacks.size(), 3);
    } finally {
        channel.close();
        log.info("end");
    }
}
Also used : ConditionCheck(com.linkedin.databus2.test.ConditionCheck) DefaultHttpChunk(org.jboss.netty.handler.codec.http.DefaultHttpChunk) ReadTimeoutException(org.jboss.netty.handler.timeout.ReadTimeoutException) Channel(org.jboss.netty.channel.Channel) DefaultHttpResponse(org.jboss.netty.handler.codec.http.DefaultHttpResponse) HttpResponse(org.jboss.netty.handler.codec.http.HttpResponse) Logger(org.apache.log4j.Logger) DefaultHttpRequest(org.jboss.netty.handler.codec.http.DefaultHttpRequest) DefaultHttpResponse(org.jboss.netty.handler.codec.http.DefaultHttpResponse) SocketAddress(java.net.SocketAddress) InetSocketAddress(java.net.InetSocketAddress) DefaultHttpChunk(org.jboss.netty.handler.codec.http.DefaultHttpChunk) HttpChunk(org.jboss.netty.handler.codec.http.HttpChunk) Test(org.testng.annotations.Test)

Example 22 with ConditionCheck

use of com.linkedin.databus2.test.ConditionCheck in project databus by linkedin.

the class TestHttpResponseProcessor method testReadTimeoutNoChunking.

@Test
public void testReadTimeoutNoChunking() throws InterruptedException, DatabusException {
    final Logger log = Logger.getLogger("GenericHttpResponseHandler.testReadTimeoutNoChunking");
    final GenericHttpResponseHandler responseHandler = new GenericHttpResponseHandler(KeepAliveType.KEEP_ALIVE);
    responseHandler.getLog().setLevel(_logLevel);
    log.info("start");
    log.setLevel(_logLevel);
    TestHttpResponseProcessor respProcessor = new TestHttpResponseProcessor(log);
    TestConnectListener connectListener = new TestConnectListener(log);
    TestSendRequestListener requestListener = new TestSendRequestListener(log);
    TestCloseListener closeListener = new TestCloseListener(log);
    responseHandler.setConnectionListener(connectListener);
    Channel channel = createClientBootstrap(responseHandler);
    try {
        setListeners(responseHandler, respProcessor, requestListener, closeListener);
        ChannelFuture writeFuture = channel.write(new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/test"));
        Assert.assertTrue(writeFuture.await(1000));
        //It seems that there is a race condition between the writeFuture succeeding
        //and the writeComplete message getting to the handler. Make sure that the
        //writeComplete has got to the handler before we do anything else with
        //the channel.
        final GenericHttpResponseHandler handler = getResponseHandler(channel);
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                return handler._messageState.hasSentRequest();
            }
        }, "request sent", 1000, log);
        Channels.fireExceptionCaught(channel, new ReadTimeoutException());
        channel.close();
        final List<String> callbacks = respProcessor.getCallbacks();
        final List<String> closeCallbacks = closeListener.getCallbacks();
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                log.debug("# callbacks:" + callbacks + ";expecting 1");
                return 1 == callbacks.size() && 1 == closeCallbacks.size();
            }
        }, "waiting for response processed", 5000, null);
        final List<String> connectCallbacks = connectListener.getCallbacks();
        final List<String> requestCallbacks = requestListener.getCallbacks();
        stateSanityCheck(connectCallbacks, requestCallbacks, callbacks, closeCallbacks);
        Assert.assertTrue(callbacks.get(0).startsWith("channelException"));
        //Assert.assertEquals(callbacks.get(1), "channelClosed");  // we don't get channelClosed after exception anymore
        //make sure that no new callbacks have showed up
        Assert.assertEquals(callbacks.size(), 1);
    } finally {
        channel.close();
        log.info("end");
    }
}
Also used : ChannelFuture(org.jboss.netty.channel.ChannelFuture) ConditionCheck(com.linkedin.databus2.test.ConditionCheck) ReadTimeoutException(org.jboss.netty.handler.timeout.ReadTimeoutException) Channel(org.jboss.netty.channel.Channel) Logger(org.apache.log4j.Logger) DefaultHttpRequest(org.jboss.netty.handler.codec.http.DefaultHttpRequest) Test(org.testng.annotations.Test)

Example 23 with ConditionCheck

use of com.linkedin.databus2.test.ConditionCheck in project databus by linkedin.

the class TestNettyHttpDatabusBootstrapConnection method testServerBootstrapDisconnect.

@Test
public /**
   * This is a unit test for DDSDBUS-3537. There is a lag between a network channel disconnect and the
   * state change in AbstractNettyHttpConnection. This can cause a race condition in various requestXXX objects which
   * check the state of the connection using the network channel. As a result, they may attempt to reconnect while
   * AbstractNettyHttpConnection is still in CONNECTED state which causes an error for an incorrect transition
   * CONNECTED -> CONNECTING.
   *
   *  The test simulates the above condition by injecting a handler in the client pipeline which artificially holds up
   *  the channelClosed message. As a result we can inject a request while the netty channel is disconnected but the
   *  AbstractNettyHttpConnection object has not detected this yet.
   */
void testServerBootstrapDisconnect() throws Exception {
    final Logger log = Logger.getLogger("TestNettyHttpDatabusBootstrapConnection.testServerBootstrapDisconnect");
    log.info("starting");
    log.info("setup the client");
    TestingConnectionCallback callback = TestingConnectionCallback.createAndStart("testServerSourcesDisconnect");
    DummyRemoteExceptionHandler remoteExceptionHandler = new DummyRemoteExceptionHandler();
    final NettyHttpDatabusBootstrapConnection conn = (NettyHttpDatabusBootstrapConnection) CONN_FACTORY.createConnection(BOOTSTRAP_SERVER_INFO, callback, remoteExceptionHandler);
    try {
        log.info("initial setup");
        final List<String> sourceNamesList = Arrays.asList(SOURCE1_NAME);
        final Checkpoint cp = Checkpoint.createOnlineConsumptionCheckpoint(0);
        BootstrapCheckpointHandler cpHandler = new BootstrapCheckpointHandler(sourceNamesList);
        cpHandler.createInitialBootstrapCheckpoint(cp, 0L);
        final DummyDatabusBootstrapConnectionStateMessage bstCallback = new DummyDatabusBootstrapConnectionStateMessage(log);
        log.info("process a normal startSCN which should establish the connection");
        sendStartScnHappyPath(conn, cp, bstCallback, SOURCE1_NAME, 100L, log);
        Assert.assertTrue(conn.isConnected());
        //wait for the response
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                return null != bstCallback.getCheckpoint();
            }
        }, "wait for /startSCN response", 100, log);
        log.info("verify /startSCN response");
        final Checkpoint startScnCp = bstCallback.getCheckpoint();
        Assert.assertNotNull(startScnCp);
        Assert.assertEquals(100L, startScnCp.getBootstrapStartScn().longValue());
        log.info("instrument the client pipeline so that we can intercept and delay the channelClosed message");
        final Semaphore passMessage = new Semaphore(1);
        final CountDownLatch closeSent = new CountDownLatch(1);
        passMessage.acquire();
        conn._channel.getPipeline().addBefore("handler", "closeChannelDelay", new SimpleChannelHandler() {

            @Override
            public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
                closeSent.countDown();
                passMessage.acquire();
                try {
                    super.channelClosed(ctx, e);
                } finally {
                    passMessage.release();
                }
            }
        });
        final Channel serverChannel = getServerChannelForClientConn(conn);
        Thread asyncChannelClose = new Thread(new Runnable() {

            @Override
            public void run() {
                log.info("closing server channel");
                serverChannel.close();
                log.info("server channel: closed");
                closeSent.countDown();
            }
        }, "asyncChannelCloseThread");
        asyncChannelClose.setDaemon(true);
        Thread asyncBootstrapReq = new Thread(new Runnable() {

            @Override
            public void run() {
                conn.requestStream("1", null, 10000, startScnCp, bstCallback);
            }
        }, "asyncBootstrapReqThread");
        asyncBootstrapReq.setDaemon(true);
        log.info("simultaneously closing connection and sending /bootstrap request");
        bstCallback.reset();
        asyncChannelClose.start();
        Assert.assertTrue(closeSent.await(1000, TimeUnit.MILLISECONDS));
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                return !conn._channel.isConnected();
            }
        }, "waiting for disconnect on the client side", 1000, log);
        Assert.assertEquals(AbstractNettyHttpConnection.State.CONNECTED, conn.getNetworkState());
        log.info("asynchronously sending /bootstrap");
        asyncBootstrapReq.start();
        log.info("letting channelClose get through");
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                return bstCallback.isStreamRequestError();
            }
        }, "wait for streamRequestError callback", 1000, log);
        passMessage.release();
        log.info("finished");
    } finally {
        conn.close();
        callback.shutdown();
        log.info("cleaned");
    }
}
Also used : ConditionCheck(com.linkedin.databus2.test.ConditionCheck) ChunkedBodyReadableByteChannel(com.linkedin.databus.client.ChunkedBodyReadableByteChannel) Channel(org.jboss.netty.channel.Channel) ChannelHandlerContext(org.jboss.netty.channel.ChannelHandlerContext) Semaphore(java.util.concurrent.Semaphore) Logger(org.apache.log4j.Logger) CountDownLatch(java.util.concurrent.CountDownLatch) BootstrapCheckpointHandler(com.linkedin.databus.core.BootstrapCheckpointHandler) InvalidConfigException(com.linkedin.databus.core.util.InvalidConfigException) JsonGenerationException(org.codehaus.jackson.JsonGenerationException) JsonMappingException(org.codehaus.jackson.map.JsonMappingException) IOException(java.io.IOException) Checkpoint(com.linkedin.databus.core.Checkpoint) ChannelStateEvent(org.jboss.netty.channel.ChannelStateEvent) SimpleChannelHandler(org.jboss.netty.channel.SimpleChannelHandler) Test(org.testng.annotations.Test)

Example 24 with ConditionCheck

use of com.linkedin.databus2.test.ConditionCheck in project databus by linkedin.

the class DummyRemoteExceptionHandler method testServerRandomScenario.

/**
   * <p>Random sequence of test iterations
   */
@Test
public void testServerRandomScenario() throws IOException, ScnNotFoundException, OffsetNotFoundException {
    final Logger log = Logger.getLogger("TestNettyHttpDatabusRelayConnection.testServerRandomScenario");
    log.info("in");
    DbusEventBuffer buf = createSimpleBuffer();
    TestingConnectionCallback callback = TestingConnectionCallback.createAndStart("testServerRandomScenario");
    DummyRemoteExceptionHandler remoteExceptionHandler = new DummyRemoteExceptionHandler();
    final NettyHttpDatabusRelayConnection conn = (NettyHttpDatabusRelayConnection) CONN_FACTORY.createRelayConnection(RELAY_SERVER_INFO, callback, remoteExceptionHandler);
    conn.getHandler().getLog().setLevel(_logLevel);
    try {
        final int iterNum = 15;
        Random rng = new Random();
        for (int i = 1; i <= iterNum; ++i) {
            int testId = rng.nextInt(10);
            switch(testId) {
                case 0:
                    {
                        log.info("======> step " + i + ": runHappyPathIteration");
                        runHappyPathIteration(log, buf, callback, remoteExceptionHandler, conn);
                        break;
                    }
                case 1:
                    {
                        log.info("======> step " + i + ": runServerSourcesDisconnectIteration");
                        runServerSourcesDisconnectIteration(log, callback, remoteExceptionHandler, conn);
                        conn.getHandler().reset();
                        break;
                    }
                case 2:
                    {
                        log.info("======> step " + i + ": runServerSourcesReadTimeoutIteration");
                        runServerSourcesReadTimeoutIteration(log, callback, remoteExceptionHandler, conn);
                        conn.getHandler().reset();
                        break;
                    }
                case 3:
                    {
                        log.info("======> step " + i + ": runServerRegisterDisconnectIteration");
                        runServerRegisterDisconnectIteration(log, callback, remoteExceptionHandler, conn);
                        conn.getHandler().reset();
                        break;
                    }
                case 4:
                    {
                        log.info("======> step " + i + ": runServerRegisterReqDisconnectIteration");
                        runServerRegisterReqDisconnectIteration(log, callback, remoteExceptionHandler, conn);
                        conn.getHandler().reset();
                        break;
                    }
                case 5:
                    {
                        log.info("======> step " + i + ": runServerRegisterReadTimeoutIteration");
                        runServerRegisterReadTimeoutIteration(log, callback, remoteExceptionHandler, conn);
                        conn.getHandler().reset();
                        break;
                    }
                case 6:
                    {
                        log.info("======> step " + i + ": runServerStreamDisconnectIteration");
                        runServerStreamDisconnectIteration(log, callback, remoteExceptionHandler, conn);
                        conn.getHandler().reset();
                        break;
                    }
                case 7:
                    {
                        log.info("======> step " + i + ": runServerStreamReqDisconnectIteration");
                        runServerStreamReqDisconnectIteration(log, callback, remoteExceptionHandler, conn);
                        conn.getHandler().reset();
                        break;
                    }
                case 8:
                    {
                        log.info("======> step " + i + ": runServerStreamReadTimeoutIteration");
                        runServerStreamReadTimeoutIteration(log, callback, remoteExceptionHandler, conn);
                        conn.getHandler().reset();
                        break;
                    }
                case 9:
                    {
                        log.info("======> step " + i + ": runServerPartialStreamTimeoutIteration");
                        runServerPartialStreamTimeoutIteration(log, buf, callback, remoteExceptionHandler, conn);
                        conn.getHandler().reset();
                        break;
                    }
                default:
                    {
                        Assert.fail("step " + i + ": unknown test id: " + testId);
                    }
                    log.info("======> step " + i + ": complete.");
                    if (0 != testId) {
                        //if it was an iteration with an error, sleep a bit until we make sure the client
                        //channel has been disconnected
                        TestUtil.assertWithBackoff(new ConditionCheck() {

                            @Override
                            public boolean check() {
                                return !conn._channel.isConnected();
                            }
                        }, "wait for child channel closure ", 1024, log);
                    }
            }
        }
    } finally {
        conn.close();
        callback.shutdown();
        log.info("out");
    }
}
Also used : ConditionCheck(com.linkedin.databus2.test.ConditionCheck) Random(java.util.Random) Logger(org.apache.log4j.Logger) Checkpoint(com.linkedin.databus.core.Checkpoint) DbusEventBuffer(com.linkedin.databus.core.DbusEventBuffer) Test(org.testng.annotations.Test)

Example 25 with ConditionCheck

use of com.linkedin.databus2.test.ConditionCheck in project databus by linkedin.

the class DummyRemoteExceptionHandler method runHappyPathIteration.

private void runHappyPathIteration(final Logger log, DbusEventBuffer buf, TestingConnectionCallback callback, DummyRemoteExceptionHandler remoteExceptionHandler, final NettyHttpDatabusRelayConnection conn) throws JsonGenerationException, JsonMappingException, IOException, ScnNotFoundException, OffsetNotFoundException {
    //connect to server and send /sources
    TestResponseProcessors.TestConnectionStateMessage msg = new TestResponseProcessors.TestConnectionStateMessage();
    conn.requestSources(msg);
    waitForServerConnection(conn, log);
    //introspect connection to server
    Channel channel = conn._channel;
    final SocketAddress clientAddr = channel.getLocalAddress();
    TestUtil.assertWithBackoff(new ConditionCheck() {

        @Override
        public boolean check() {
            return null != _dummyServer.getChildChannel(clientAddr);
        }
    }, "client connection established", 1000, log);
    Channel serverChannel = _dummyServer.getChildChannel(clientAddr);
    ChannelPipeline serverPipeline = serverChannel.getPipeline();
    SimpleObjectCaptureHandler objCapture = (SimpleObjectCaptureHandler) serverPipeline.get("3");
    //verify server gets the /source request
    HttpResponse sourcesResp = runHappyPathSources(log, callback, remoteExceptionHandler, clientAddr, objCapture);
    //send /register
    runHappyPathRegister(log, callback, remoteExceptionHandler, conn, msg, clientAddr, objCapture, sourcesResp);
    //send /stream
    runHappyPathStream(log, buf, callback, remoteExceptionHandler, conn, msg, clientAddr, objCapture, sourcesResp);
    callback.clearLastMsg();
    objCapture.clear();
}
Also used : ConditionCheck(com.linkedin.databus2.test.ConditionCheck) SimpleObjectCaptureHandler(com.linkedin.databus2.test.container.SimpleObjectCaptureHandler) Channel(org.jboss.netty.channel.Channel) DefaultHttpResponse(org.jboss.netty.handler.codec.http.DefaultHttpResponse) HttpResponse(org.jboss.netty.handler.codec.http.HttpResponse) SocketAddress(java.net.SocketAddress) InetSocketAddress(java.net.InetSocketAddress) ChannelPipeline(org.jboss.netty.channel.ChannelPipeline)

Aggregations

ConditionCheck (com.linkedin.databus2.test.ConditionCheck)47 Test (org.testng.annotations.Test)40 Logger (org.apache.log4j.Logger)36 Channel (org.jboss.netty.channel.Channel)22 InetSocketAddress (java.net.InetSocketAddress)21 Checkpoint (com.linkedin.databus.core.Checkpoint)20 DefaultHttpResponse (org.jboss.netty.handler.codec.http.DefaultHttpResponse)20 HttpResponse (org.jboss.netty.handler.codec.http.HttpResponse)20 SocketAddress (java.net.SocketAddress)19 RegisterResponseEntry (com.linkedin.databus2.core.container.request.RegisterResponseEntry)15 DefaultHttpChunk (org.jboss.netty.handler.codec.http.DefaultHttpChunk)15 HttpChunk (org.jboss.netty.handler.codec.http.HttpChunk)15 DbusEventBuffer (com.linkedin.databus.core.DbusEventBuffer)12 ArrayList (java.util.ArrayList)11 HashMap (java.util.HashMap)11 ChannelPipeline (org.jboss.netty.channel.ChannelPipeline)11 DefaultHttpRequest (org.jboss.netty.handler.codec.http.DefaultHttpRequest)11 SimpleObjectCaptureHandler (com.linkedin.databus2.test.container.SimpleObjectCaptureHandler)10 List (java.util.List)10 IdNamePair (com.linkedin.databus.core.util.IdNamePair)9