Package org.atmosphere.nettosphere.test

Source Code of org.atmosphere.nettosphere.test.NettyAtmosphereTest

/*
* Copyright 2013 Jeanfrancois Arcand
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.atmosphere.nettosphere.test;

import com.ning.http.client.AsyncHandler;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClientConfig;
import com.ning.http.client.HttpResponseBodyPart;
import com.ning.http.client.HttpResponseHeaders;
import com.ning.http.client.HttpResponseStatus;
import com.ning.http.client.Response;
import com.ning.http.client.SSLEngineFactory;
import com.ning.http.client.websocket.WebSocket;
import com.ning.http.client.websocket.WebSocketTextListener;
import com.ning.http.client.websocket.WebSocketUpgradeHandler;
import org.atmosphere.cpr.AtmosphereHandler;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
import org.atmosphere.nettosphere.Config;
import org.atmosphere.nettosphere.Handler;
import org.atmosphere.nettosphere.Nettosphere;
import org.atmosphere.websocket.WebSocketEventListenerAdapter;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import static org.atmosphere.cpr.HeaderConfig.LONG_POLLING_TRANSPORT;
import static org.atmosphere.cpr.HeaderConfig.X_ATMOSPHERE_TRANSPORT;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;

public class NettyAtmosphereTest extends BaseTest {
    private final static String RESUME = "Resume";

    protected int port;
    protected Nettosphere server;
    private String targetUrl;
    private String wsUrl;

    @AfterMethod(alwaysRun = true)
    public void tearDownGlobal() throws Exception {
        server.stop();
    }

    @BeforeMethod(alwaysRun = true)
    public void start() throws IOException {
        port = findFreePort();
        targetUrl = "http://127.0.0.1:" + port;
        wsUrl = "ws://127.0.0.1:" + port;
    }

    @Test
    public void initParamTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);
        final AtomicBoolean b = new AtomicBoolean(false);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .initParam("foo", "bar")
                .resource("/suspend", new AtmosphereHandler() {

                    @Override
                    public void onRequest(AtmosphereResource r) throws IOException {
                        if (r.getAtmosphereConfig().getInitParameter("foo") != null) {
                            b.set(true);
                        }
                        l.countDown();
                    }

                    @Override
                    public void onStateChange(AtmosphereResourceEvent r) throws IOException {
                    }

                    @Override
                    public void destroy() {

                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();

        assertNotNull(server);
        server.start();

        AsyncHttpClient c = new AsyncHttpClient();
        Response r = c.prepareGet(targetUrl + "/suspend").execute().get();

        assertEquals(r.getStatusCode(), 200);
        assertEquals(b.get(), true);

    }

    @Test
    public void suspendLongPollingTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);
        final CountDownLatch suspendCD = new CountDownLatch(1);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .resource("/suspend", new AtmosphereHandler() {

                    private final AtomicBoolean b = new AtomicBoolean(false);

                    @Override
                    public void onRequest(AtmosphereResource r) throws IOException {
                        if (!b.getAndSet(true)) {
                            r.addEventListener(new WebSocketEventListenerAdapter() {
                                @Override
                                public void onSuspend(AtmosphereResourceEvent e) {
                                    suspendCD.countDown();
                                }
                            });
                            r.suspend(-1);
                        } else {
                            r.getBroadcaster().broadcast(RESUME);
                        }
                    }

                    @Override
                    public void onStateChange(AtmosphereResourceEvent r) throws IOException {
                        if (r.isSuspended()) {
                            r.getResource().getResponse().getWriter().print(r.getMessage());
                            r.getResource().resume();
                        }
                    }

                    @Override
                    public void destroy() {

                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();

        assertNotNull(server);
        server.start();

        final AtomicReference<Response> response = new AtomicReference<Response>();
        AsyncHttpClient c = new AsyncHttpClient();
        c.prepareGet(targetUrl + "/suspend").setHeader(X_ATMOSPHERE_TRANSPORT, LONG_POLLING_TRANSPORT).execute(new AsyncHandler<Response>() {

            final Response.ResponseBuilder b = new Response.ResponseBuilder();

            @Override
            public void onThrowable(Throwable t) {
                l.countDown();
            }

            @Override
            public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
                b.accumulate(bodyPart);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
                b.accumulate(responseStatus);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
                b.accumulate(headers);
                return STATE.CONTINUE;
            }

            @Override
            public Response onCompleted() throws Exception {
                response.set(b.build());

                l.countDown();
                return null;
            }
        });

        suspendCD.await(5, TimeUnit.SECONDS);

        Response r = c.prepareGet(targetUrl + "/suspend").execute().get();
        assertEquals(r.getStatusCode(), 200);

        l.await(5, TimeUnit.SECONDS);

        assertEquals(response.get().getStatusCode(), 200);
        assertEquals(response.get().getResponseBody().trim(), RESUME);
    }

    @Test
    public void suspendStreamingTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);
        final CountDownLatch suspendCD = new CountDownLatch(1);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .resource("/suspend", new AtmosphereHandler() {

                    private final AtomicBoolean suspended = new AtomicBoolean(false);

                    @Override
                    public void onRequest(AtmosphereResource r) throws IOException {
                        if (!suspended.getAndSet(true)) {
                            r.suspend(-1);
                            suspendCD.countDown();
                        } else {
                            r.getBroadcaster().broadcast(RESUME);
                        }
                    }

                    @Override
                    public void onStateChange(AtmosphereResourceEvent r) throws IOException {
                        if (suspended.get()) {
                            r.getResource().getResponse().getWriter().print(r.getMessage());
                            r.getResource().resume();
                        }
                    }

                    @Override
                    public void destroy() {

                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();

        assertNotNull(server);
        server.start();

        final AtomicReference<Response> response = new AtomicReference<Response>();
        AsyncHttpClient c = new AsyncHttpClient();
        c.prepareGet(targetUrl + "/suspend").setHeader(X_ATMOSPHERE_TRANSPORT, "streaming").execute(new AsyncHandler<Response>() {

            final Response.ResponseBuilder b = new Response.ResponseBuilder();

            @Override
            public void onThrowable(Throwable t) {
                l.countDown();
            }

            @Override
            public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
                b.accumulate(bodyPart);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
                b.accumulate(responseStatus);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
                b.accumulate(headers);
                return STATE.CONTINUE;
            }

            @Override
            public Response onCompleted() throws Exception {
                response.set(b.build());

                l.countDown();
                return null;
            }
        });

        suspendCD.await(5, TimeUnit.SECONDS);

        Response r = c.prepareGet(targetUrl + "/suspend").execute().get();
        assertEquals(r.getStatusCode(), 200);

        l.await(5, TimeUnit.SECONDS);

        assertEquals(response.get().getStatusCode(), 200);
        assertEquals(response.get().getResponseBody().trim(), RESUME);
    }

    @Test
    public void suspendWebSocketTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .resource("/suspend", new AtmosphereHandler() {

                    private final AtomicBoolean b = new AtomicBoolean(false);

                    @Override
                    public void onRequest(AtmosphereResource r) throws IOException {
                        if (!b.getAndSet(true)) {
                            r.suspend(-1);
                        } else {
                            r.getBroadcaster().broadcast(RESUME);
                        }
                    }

                    @Override
                    public void onStateChange(AtmosphereResourceEvent r) throws IOException {
                        if (!r.isResuming() || !r.isCancelled()) {
                            r.getResource().getResponse().getWriter().print(r.getMessage());
                            r.getResource().resume();
                        }
                    }

                    @Override
                    public void destroy() {

                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();
        assertNotNull(server);
        server.start();

        final AtomicReference<String> response = new AtomicReference<String>();
        AsyncHttpClient c = new AsyncHttpClient();
        WebSocket webSocket = c.prepareGet(wsUrl + "/suspend").execute(new WebSocketUpgradeHandler.Builder().build()).get();
        assertNotNull(webSocket);
        webSocket.addWebSocketListener(new WebSocketTextListener() {
            @Override
            public void onMessage(String message) {
                response.set(message);
                l.countDown();
            }

            @Override
            public void onFragment(String fragment, boolean last) {
            }

            @Override
            public void onOpen(WebSocket websocket) {
            }

            @Override
            public void onClose(WebSocket websocket) {
                l.countDown();
            }

            @Override
            public void onError(Throwable t) {
                l.countDown();
            }
        }).sendTextMessage("Ping");

        l.await(5, TimeUnit.SECONDS);

        webSocket.close();
        assertEquals(response.get(), RESUME);

    }

    @Test
    public void webSocketHandlerTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .resource(new Handler() {

                    @Override
                    public void handle(AtmosphereResource r) {
                        r.getResponse().write("Hello World from Nettosphere").closeStreamOrWriter();
                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();
        assertNotNull(server);
        server.start();

        final AtomicReference<String> response = new AtomicReference<String>();
        AsyncHttpClient c = new AsyncHttpClient();
        WebSocket webSocket = c.prepareGet(wsUrl).execute(new WebSocketUpgradeHandler.Builder().build()).get();
        assertNotNull(webSocket);
        webSocket.addWebSocketListener(new WebSocketTextListener() {
            @Override
            public void onMessage(String message) {
                response.set(message);
                l.countDown();
            }

            @Override
            public void onFragment(String fragment, boolean last) {
            }

            @Override
            public void onOpen(WebSocket websocket) {
            }

            @Override
            public void onClose(WebSocket websocket) {
            }

            @Override
            public void onError(Throwable t) {
            }
        });

        l.await(5, TimeUnit.SECONDS);

        webSocket.close();
        assertEquals(response.get(), "Hello World from Nettosphere");

    }

    @Test
    public void httpHandlerTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .resource(new Handler() {

                    @Override
                    public void handle(AtmosphereResource r) {
                        r.getResponse().write("Hello World from Nettosphere").closeStreamOrWriter();
                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();
        assertNotNull(server);
        server.start();

        AsyncHttpClient c = new AsyncHttpClient();
        Response response = c.prepareGet(targetUrl).execute().get();
        assertNotNull(response);

        assertEquals(response.getResponseBody(), "Hello World from Nettosphere");

    }

    @Test
    public void httspHandlerTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);
        final SSLContext sslContext = createSSLContext();
        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .sslContext(sslContext)
                .resource(new Handler() {

                    @Override
                    public void handle(AtmosphereResource r) {
                        r.getResponse().write("Hello World from Nettosphere").closeStreamOrWriter();
                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();
        assertNotNull(server);
        server.start();

        AsyncHttpClient c = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setSSLEngineFactory(new SSLEngineFactory() {

            @Override
            public SSLEngine newSSLEngine() throws GeneralSecurityException {
                    SSLEngine sslEngine = sslContext.createSSLEngine();
                    sslEngine.setUseClientMode(true);
                    sslEngine.setEnabledCipherSuites(new String[]{"SSL_DH_anon_WITH_RC4_128_MD5"});
                    return sslEngine;
            }
        }).build());
        Response response = c.prepareGet("https://127.0.0.1:" + port).execute().get();
        assertNotNull(response);

        assertEquals(response.getResponseBody(), "Hello World from Nettosphere");

    }

    @Test
    public void wssHandlerTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);
        final SSLContext sslContext = createSSLContext();
        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .sslContext(sslContext)
                .resource(new Handler() {

                    @Override
                    public void handle(AtmosphereResource r) {
                        r.getResponse().write("Hello World from Nettosphere").closeStreamOrWriter();
                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();
        assertNotNull(server);
        server.start();

        AsyncHttpClient c = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setSSLEngineFactory(new SSLEngineFactory() {

            @Override
            public SSLEngine newSSLEngine() throws GeneralSecurityException {
                    SSLEngine sslEngine = sslContext.createSSLEngine();
                    sslEngine.setUseClientMode(true);
                    sslEngine.setEnabledCipherSuites(new String[]{"SSL_DH_anon_WITH_RC4_128_MD5"});
                    return sslEngine;
            }
        }).build());

        final AtomicReference<String> response = new AtomicReference<String>();
        WebSocket webSocket = c.prepareGet("wss://127.0.0.1:" + port).execute(new WebSocketUpgradeHandler.Builder().build()).get();
        assertNotNull(webSocket);
        webSocket.addWebSocketListener(new WebSocketTextListener() {
            @Override
            public void onMessage(String message) {
                response.set(message);
                l.countDown();
            }

            @Override
            public void onFragment(String fragment, boolean last) {
            }

            @Override
            public void onOpen(WebSocket websocket) {
            }

            @Override
            public void onClose(WebSocket websocket) {
            }

            @Override
            public void onError(Throwable t) {
            }
        });

        l.await(5, TimeUnit.SECONDS);

        webSocket.close();
        assertEquals(response.get(), "Hello World from Nettosphere");

    }

    private static SSLContext createSSLContext() {
        try {
            InputStream keyStoreStream = BaseTest.class.getResourceAsStream("ssltest-cacerts.jks");
            char[] keyStorePassword = "changeit".toCharArray();
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(keyStoreStream, keyStorePassword);

            // Set up key manager factory to use our key store
            char[] certificatePassword = "changeit".toCharArray();
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, certificatePassword);

            // Initialize the SSLContext to work with our key managers.
            KeyManager[] keyManagers = kmf.getKeyManagers();
            TrustManager[] trustManagers = new TrustManager[]{DUMMY_TRUST_MANAGER};
            SecureRandom secureRandom = new SecureRandom();

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(keyManagers, trustManagers, secureRandom);
            return sslContext;
        } catch (Exception e) {
            throw new Error("Failed to initialize SSLContext", e);
        }
    }

    private static final AtomicBoolean TRUST_SERVER_CERT = new AtomicBoolean(true);
    private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            if (!TRUST_SERVER_CERT.get()) {
                throw new CertificateException("Server certificate not trusted.");
            }
        }
    };

    @Test
    public void closeTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);
        final CountDownLatch suspendCD = new CountDownLatch(1);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .resource("/suspend", new AtmosphereHandler() {


                    @Override
                    public void onRequest(AtmosphereResource r) throws IOException {
                        r.addEventListener(new WebSocketEventListenerAdapter() {
                            @Override
                            public void onSuspend(AtmosphereResourceEvent e) {
                                suspendCD.countDown();
                            }
                        });
                        r.suspend(60, TimeUnit.SECONDS);
                    }

                    @Override
                    public void onStateChange(AtmosphereResourceEvent r) throws IOException {
                    }

                    @Override
                    public void destroy() {

                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();

        assertNotNull(server);
        server.start();

        final AtomicReference<HttpResponseHeaders> response = new AtomicReference<HttpResponseHeaders>();
        AsyncHttpClient c = new AsyncHttpClient();
        c.prepareGet(targetUrl + "/suspend").execute(new AsyncHandler<Response>() {

            final Response.ResponseBuilder b = new Response.ResponseBuilder();

            @Override
            public void onThrowable(Throwable t) {
                l.countDown();
            }

            @Override
            public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
                return STATE.CONTINUE;
            }

            @Override
            public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
                return STATE.CONTINUE;
            }

            @Override
            public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
                response.set(headers);
                l.countDown();
                return STATE.ABORT;
            }

            @Override
            public Response onCompleted() throws Exception {
                return null;
            }
        });

        suspendCD.await(5, TimeUnit.SECONDS);

        Thread.sleep(2000);

        server.stop();
        l.await(20, TimeUnit.SECONDS);

        assertNotNull(response.get());
    }

    @Test
    public void suspendNoChunkStreamingTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);
        final CountDownLatch suspendCD = new CountDownLatch(1);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .supportChunking(false)
                .resource("/suspend", new AtmosphereHandler() {

                    private final AtomicBoolean suspended = new AtomicBoolean(false);

                    @Override
                    public void onRequest(AtmosphereResource r) throws IOException {
                        if (!suspended.getAndSet(true)) {
                            r.suspend(-1);
                            suspendCD.countDown();
                        } else {
                            r.getBroadcaster().broadcast(RESUME);
                        }
                    }

                    @Override
                    public void onStateChange(AtmosphereResourceEvent r) throws IOException {
                        if (suspended.get()) {
                            r.getResource().getResponse().getWriter().print(r.getMessage());
                            r.getResource().resume();
                        }
                    }

                    @Override
                    public void destroy() {

                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();

        assertNotNull(server);
        server.start();

        final AtomicReference<Response> response = new AtomicReference<Response>();
        AsyncHttpClient c = new AsyncHttpClient();
        c.prepareGet(targetUrl + "/suspend").setHeader(X_ATMOSPHERE_TRANSPORT, "streaming").execute(new AsyncHandler<Response>() {

            final Response.ResponseBuilder b = new Response.ResponseBuilder();

            @Override
            public void onThrowable(Throwable t) {
                l.countDown();
            }

            @Override
            public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
                b.accumulate(bodyPart);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
                b.accumulate(responseStatus);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
                b.accumulate(headers);
                return STATE.CONTINUE;
            }

            @Override
            public Response onCompleted() throws Exception {
                response.set(b.build());

                l.countDown();
                return null;
            }
        });

        suspendCD.await(5, TimeUnit.SECONDS);

        Response r = c.prepareGet(targetUrl + "/suspend").execute().get();
        assertEquals(r.getStatusCode(), 200);

        l.await(5, TimeUnit.SECONDS);

        assertEquals(response.get().getStatusCode(), 200);
        assertEquals(response.get().getResponseBody().trim(), RESUME);
    }

    @Test
    public void aggregatePostInMemoryTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);
        final CountDownLatch suspendCD = new CountDownLatch(1);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .supportChunking(false)
                .aggregateRequestBodyInMemory(false)
                .resource("/suspend", new AtmosphereHandler() {

                    private final AtomicBoolean suspended = new AtomicBoolean(false);

                    @Override
                    public void onRequest(AtmosphereResource r) throws IOException {
                        if (!suspended.getAndSet(true)) {
                            r.suspend(-1);
                            suspendCD.countDown();
                        } else {
                            r.getBroadcaster().broadcast(new String(r.getRequest().body().asBytes()));
                        }
                    }

                    @Override
                    public void onStateChange(AtmosphereResourceEvent r) throws IOException {
                        if (suspended.get()) {
                            r.getResource().getResponse().getWriter().print(r.getMessage());
                            if (r.getMessage().toString().contains("message")) {
                                r.getResource().resume();
                            }
                        }
                    }

                    @Override
                    public void destroy() {

                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();

        assertNotNull(server);
        server.start();

        final AtomicReference<Response> response = new AtomicReference<Response>();
        AsyncHttpClient c = new AsyncHttpClient();
        c.prepareGet(targetUrl + "/suspend").setHeader(X_ATMOSPHERE_TRANSPORT, "streaming").execute(new AsyncHandler<Response>() {

            final Response.ResponseBuilder b = new Response.ResponseBuilder();

            @Override
            public void onThrowable(Throwable t) {
                l.countDown();
            }

            @Override
            public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
                b.accumulate(bodyPart);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
                b.accumulate(responseStatus);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
                b.accumulate(headers);
                return STATE.CONTINUE;
            }

            @Override
            public Response onCompleted() throws Exception {
                response.set(b.build());

                l.countDown();
                return null;
            }
        });

        suspendCD.await(5, TimeUnit.SECONDS);

        StringBuilder b = new StringBuilder();
        for (int i=0; i < 10000; i++) {
            b.append("======");
        }
        b.append("message");

        Response r = c.preparePost(targetUrl + "/suspend").setContentLength(b.toString().length()).setBody(b.toString()).execute().get();
        assertEquals(r.getStatusCode(), 200);

        l.await(5, TimeUnit.SECONDS);

        assertEquals(response.get().getStatusCode(), 200);
        assertEquals(response.get().getResponseBody().trim(), b.toString());
    }

    @Test
    public void chunkPostInMemoryTest() throws Exception {
        final CountDownLatch l = new CountDownLatch(1);
        final CountDownLatch suspendCD = new CountDownLatch(1);

        Config config = new Config.Builder()
                .port(port)
                .host("127.0.0.1")
                .supportChunking(true)
                .aggregateRequestBodyInMemory(false)
                .resource("/suspend", new AtmosphereHandler() {

                    private final AtomicBoolean suspended = new AtomicBoolean(false);

                    @Override
                    public void onRequest(AtmosphereResource r) throws IOException {
                        if (!suspended.getAndSet(true)) {
                            r.suspend(-1);
                            suspendCD.countDown();
                        } else {
                            r.getBroadcaster().broadcast(new String(r.getRequest().body().asBytes()));
                        }
                    }

                    @Override
                    public void onStateChange(AtmosphereResourceEvent r) throws IOException {
                        if (r.isSuspended()) {
                            r.getResource().getResponse().getWriter().print(r.getMessage());
                            if (r.getMessage().toString().contains("message")) {
                                r.getResource().resume();
                            }
                        }
                    }

                    @Override
                    public void destroy() {

                    }
                }).build();

        server = new Nettosphere.Builder().config(config).build();

        assertNotNull(server);
        server.start();

        final AtomicReference<Response> response = new AtomicReference<Response>();
        AsyncHttpClient c = new AsyncHttpClient();
        c.prepareGet(targetUrl + "/suspend").setHeader(X_ATMOSPHERE_TRANSPORT, "streaming").execute(new AsyncHandler<Response>() {

            final Response.ResponseBuilder b = new Response.ResponseBuilder();

            @Override
            public void onThrowable(Throwable t) {
                l.countDown();
            }

            @Override
            public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
                b.accumulate(bodyPart);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
                b.accumulate(responseStatus);
                return STATE.CONTINUE;
            }

            @Override
            public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
                b.accumulate(headers);
                return STATE.CONTINUE;
            }

            @Override
            public Response onCompleted() throws Exception {
                response.set(b.build());

                l.countDown();
                return null;
            }
        });

        suspendCD.await(5, TimeUnit.SECONDS);

        StringBuilder b = new StringBuilder();
        for (int i=0; i < 10000; i++) {
            b.append("======");
        }
        b.append("message");

        Response r = c.preparePost(targetUrl + "/suspend").setContentLength(b.toString().length()).setBody(b.toString()).execute().get();
        assertEquals(r.getStatusCode(), 200);

        l.await(5, TimeUnit.SECONDS);

        assertEquals(response.get().getStatusCode(), 200);
        assertEquals(response.get().getResponseBody().trim(), b.toString());
    }
}
TOP

Related Classes of org.atmosphere.nettosphere.test.NettyAtmosphereTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.