org.wisdom.framework.vertx.VertxDispatcherTest.java Source code

Java tutorial

Introduction

Here is the source code for org.wisdom.framework.vertx.VertxDispatcherTest.java

Source

/*
 * #%L
 * Wisdom-Framework
 * %%
 * Copyright (C) 2013 - 2014 Wisdom Framework
 * %%
 * 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.
 * #L%
 */
package org.wisdom.framework.vertx;

import com.google.common.base.Charsets;
import io.vertx.core.Vertx;
import io.vertx.core.http.ServerWebSocket;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Test;
import org.wisdom.api.configuration.ApplicationConfiguration;
import org.wisdom.api.content.ContentEngine;
import org.wisdom.api.exceptions.ExceptionMapper;
import org.wisdom.api.http.websockets.WebSocketListener;
import org.wisdom.api.router.Router;
import org.wisdom.framework.vertx.ssl.SSLServerContext;

import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;

/**
 * Test the server.
 */
public class VertxDispatcherTest extends VertxBaseTest {

    private WisdomVertxServer server;

    Vertx vertx = Vertx.vertx();

    @After
    public void tearDown() throws InterruptedException {
        if (server != null) {
            server.stop();
            server = null;
        }

        CountDownLatch latch = new CountDownLatch(1);
        if (vertx != null) {
            vertx.close(v -> {
                latch.countDown();
            });
        }
        latch.await();
        FileUtils.deleteQuietly(new File("target/junk/conf/conf/fake.keystore"));
    }

    public void prepareHttps() throws KeyManagementException, NoSuchAlgorithmException {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }

            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        } };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = (hostname, session) -> true;

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

    }

    @Test
    public void testServerStartSequence()
            throws InterruptedException, IOException, NoSuchAlgorithmException, KeyManagementException {
        prepareHttps();
        prepareServer();
        VertxHttpServerTest.waitForStart(server);
        VertxBaseTest.waitForHttpsStart(server);

        int http = server.httpPort();
        int https = server.httpsPort();

        HttpURLConnection connection = null;
        int responseCode = 0;
        for (int i = 0; i < 10; i++) {
            URL url = new URL("http://localhost:" + http + "/test");
            try {
                connection = (HttpURLConnection) url.openConnection();
                responseCode = connection.getResponseCode();
            } catch (IOException e) {
                // Probably not yet started, waiting.
                // Wait a maximum of 20 seconds, should be enough on most machine.
                Thread.sleep(2000);
            }
        }
        System.out.println("1");
        // Here either the server has started, or something really bad happened.
        assertThat(connection).isNotNull();
        assertThat(responseCode).isEqualTo(404);
        System.out.println("2");
        connection = null;
        responseCode = 0;
        for (int i = 0; i < 10; i++) {
            URL url = new URL("https://localhost:" + https + "/test");
            try {
                connection = (HttpURLConnection) url.openConnection();

                responseCode = connection.getResponseCode();
            } catch (IOException e) {
                // Probably not yet started, waiting.
                // Wait a maximum of 20 seconds, should be enough on most machine.
                Thread.sleep(2000);
            }
        }
        System.out.println("3");
        // Here either the server has started, or something really bad happened.
        assertThat(connection).isNotNull();
        assertThat(responseCode).isEqualTo(404);

        assertThat(server.hostname()).isEqualTo("localhost");
        assertThat(server.httpPort()).isGreaterThan(9000);
        assertThat(server.httpsPort()).isGreaterThan(9001);
    }

    @Test
    public void testWebSocketDispatching() throws InterruptedException {
        // Prepare the configuration
        ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
        when(configuration.getIntegerWithDefault(eq("vertx.http.port"), anyInt())).thenReturn(-1);
        when(configuration.getIntegerWithDefault(eq("vertx.https.port"), anyInt())).thenReturn(-1);

        // Prepare an empty router.
        Router router = mock(Router.class);
        ContentEngine contentEngine = mock(ContentEngine.class);

        // Configure the server.
        server = new WisdomVertxServer();
        server.accessor = new ServiceAccessor(null, configuration, router, contentEngine, null, null,
                Collections.<ExceptionMapper>emptyList());
        server.configuration = configuration;
        server.vertx = vertx;

        server.start();

        final ServerWebSocket socket = mock(ServerWebSocket.class);
        final Socket sock = new Socket(socket);
        server.addSocket("/hello", sock);

        MyWebSocketListener listener = new MyWebSocketListener();
        server.register(listener);
        // The listener should have been notified.
        assertThat(listener.opened).isNotNull();

        server.received("/hello", "message".getBytes(Charsets.UTF_8), sock);

        // The listener should have received the message.
        assertThat(listener.lastMessage).isEqualTo("message");
        assertThat(listener.lastClient).isNotNull();
        assertThat(listener.closed).isNull();

        server.received("/hello", "message2".getBytes(Charsets.UTF_8), sock);
        assertThat(listener.lastMessage).isEqualTo("message2");
        assertThat(listener.lastClient).isNotNull();
        assertThat(listener.closed).isNull();

        server.removeSocket("/hello", sock);
        assertThat(listener.closed).isNotNull();

    }

    @Test
    public void testWebSocketWithMultiClients() throws InterruptedException, IOException {
        // Prepare the configuration
        prepareServer();

        final ServerWebSocket socket1 = mock(ServerWebSocket.class);
        final Socket sock1 = new Socket(socket1);
        final ServerWebSocket socket2 = mock(ServerWebSocket.class);
        final Socket sock2 = new Socket(socket2);

        MyWebSocketListener listener = new MyWebSocketListener();
        server.register(listener);

        server.addSocket("/hello", sock1);
        // The listener should have been notified.
        assertThat(listener.opened).isNotNull();
        server.received("/hello", "message".getBytes(Charsets.UTF_8), sock1);

        // The listener should have received the message.
        assertThat(listener.lastMessage).isEqualTo("message");
        assertThat(listener.lastClient).isEqualTo(Integer.toOctalString(socket1.hashCode()));

        server.addSocket("/hello", sock2);
        server.received("/hello", "message2".getBytes(Charsets.UTF_8), sock2);
        assertThat(listener.lastMessage).isEqualTo("message2");
        assertThat(listener.lastClient).isEqualTo(Integer.toOctalString(socket2.hashCode()));

        server.removeSocket("/hello", sock1);
        server.removeSocket("/hello", sock2);
        assertThat(listener.closed).isNotNull();
    }

    @Test
    public void testWebSocketSending() throws InterruptedException, IOException {
        prepareServer();

        final ServerWebSocket socket1 = mock(ServerWebSocket.class);
        final Socket sock = new Socket(socket1);
        when(socket1.textHandlerID()).thenReturn("/hello");

        MyWebSocketListener listener = new MyWebSocketListener();
        server.register(listener);

        server.addSocket("/hello", sock);
        // The listener should have been notified.
        assertThat(listener.opened).isNotNull();
        server.received("/hello", "message".getBytes(Charsets.UTF_8), sock);

        // The listener should have received the message.
        assertThat(listener.lastMessage).isEqualTo("message");
        assertThat(listener.lastClient).isEqualTo(WisdomVertxServer.id(sock));

        server.send("/hello", WisdomVertxServer.id(sock), "response");
        // Write on missing client.
        server.send("/hello", "missing", "response");
        server.publish("/hello", "yep !");

    }

    private void prepareServer() throws IOException, InterruptedException {
        ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
        when(configuration.getIntegerWithDefault(eq("vertx.http.port"), anyInt())).thenReturn(0);
        when(configuration.getIntegerWithDefault(eq("vertx.https.port"), anyInt())).thenReturn(0);
        when(configuration.getIntegerWithDefault("vertx.acceptBacklog", -1)).thenReturn(-1);
        when(configuration.getIntegerWithDefault("vertx.receiveBufferSize", -1)).thenReturn(-1);
        when(configuration.getIntegerWithDefault("vertx.sendBufferSize", -1)).thenReturn(-1);
        when(configuration.getStringArray("wisdom.websocket.subprotocols")).thenReturn(new String[0]);
        when(configuration.getStringArray("vertx.websocket-subprotocols")).thenReturn(new String[0]);
        when(configuration.getBaseDir()).thenReturn(new File("target/junk/conf"));

        // Prepare an empty router.
        Router router = mock(Router.class);

        ContentEngine contentEngine = mock(ContentEngine.class);

        // Configure the server.
        server = new WisdomVertxServer();
        server.accessor = new ServiceAccessor(null, configuration, router, contentEngine, null, null,
                Collections.<ExceptionMapper>emptyList());
        server.configuration = configuration;
        server.vertx = vertx;

        server.start();

        waitForStart(server);
    }

    private class MyWebSocketListener implements WebSocketListener {
        String lastMessage;
        String lastClient;
        String opened;
        String closed;

        @Override
        public void received(String uri, String client, byte[] content) {
            this.lastMessage = new String(content, Charsets.UTF_8);
            this.lastClient = client;
        }

        @Override
        public void opened(String uri, String client) {
            this.opened = client;
        }

        @Override
        public void closed(String uri, String client) {
            this.closed = client;
        }
    }
}