com.nesscomputing.service.discovery.server.TestStaticAnnounce.java Source code

Java tutorial

Introduction

Here is the source code for com.nesscomputing.service.discovery.server.TestStaticAnnounce.java

Source

/**
 * Copyright (C) 2012 Ness Computing, Inc.
 *
 * 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 com.nesscomputing.service.discovery.server;

import static java.lang.String.format;
import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.URI;
import java.util.List;
import java.util.Map;

import javax.ws.rs.core.MediaType;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;
import com.google.common.net.HttpHeaders;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Stage;
import com.google.inject.name.Named;

import org.apache.commons.configuration.SystemConfiguration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.nesscomputing.config.Config;
import com.nesscomputing.config.ConfigModule;
import com.nesscomputing.httpclient.HttpClient;
import com.nesscomputing.httpclient.guice.HttpClientModule;
import com.nesscomputing.httpclient.response.ContentResponseHandler;
import com.nesscomputing.httpclient.response.HttpResponse;
import com.nesscomputing.httpclient.response.HttpResponseContentConverter;
import com.nesscomputing.httpclient.response.JsonContentConverter;
import com.nesscomputing.httpclient.response.Valid2xxContentConverter;
import com.nesscomputing.jackson.NessJacksonModule;
import com.nesscomputing.lifecycle.Lifecycle;
import com.nesscomputing.lifecycle.LifecycleStage;
import com.nesscomputing.lifecycle.ServiceDiscoveryLifecycle;
import com.nesscomputing.lifecycle.guice.LifecycleModule;
import com.nesscomputing.logging.Log;
import com.nesscomputing.server.StandaloneServer;
import com.nesscomputing.service.discovery.client.DiscoveryClientModule;
import com.nesscomputing.service.discovery.client.ReadOnlyDiscoveryClient;
import com.nesscomputing.service.discovery.client.ServiceInformation;
import com.nesscomputing.service.discovery.client.ServiceNotAvailableException;
import com.nesscomputing.testing.lessio.AllowLocalFileAccess;
import com.nesscomputing.testing.lessio.AllowNetworkAccess;
import com.nesscomputing.testing.lessio.AllowNetworkListen;

@AllowLocalFileAccess(paths = { "%TMP_DIR%" })
@AllowNetworkListen(ports = { 0 })
@AllowNetworkAccess(endpoints = { "127.0.0.1:0" })
public class TestStaticAnnounce {
    private static final Log LOG = Log.findLog();
    StandaloneServer server;
    String serverBase;

    @Inject
    Lifecycle lifecycle;

    @Inject
    ReadOnlyDiscoveryClient discoveryClient;

    @Inject
    @Named("test")
    HttpClient httpClient;

    @Inject
    ObjectMapper objectMapper;

    @Before
    public void spinup() throws Exception {
        System.setProperty("ness.discovery.enabled", "true");
        server = new DiscoveryServerMain() {
            @Override
            public Config getConfig() {
                final File tmpDir = Files.createTempDir();
                tmpDir.deleteOnExit();
                final String httpPort = Integer.toString(findUnusedPort());

                serverBase = "http://localhost:" + httpPort;

                System.setProperty("galaxy.internal.port.http", httpPort);
                System.setProperty("ness.zookeeper.dataDir", tmpDir.getAbsolutePath());
                System.setProperty("ness.zookeeper.clientPort", Integer.toString(findUnusedPort()));
                System.setProperty("ness.jmx.enabled", "false");

                final int port1 = findUnusedPort();
                final int port2 = findUnusedPort();
                System.setProperty("ness.zookeeper.server.1", format("127.0.0.1:%d:%d", port1, port2));
                System.setProperty("ness.zookeeper.clientPortAddress", "127.0.0.1");

                return Config.getConfig(URI.create("classpath:/config"), "discovery-server");
            }
        };

        server.startServer();

        Guice.createInjector(Stage.PRODUCTION, new AbstractModule() {
            @Override
            protected void configure() {
                binder().requireExplicitBindings();
                binder().disableCircularProxies();

                install(new ConfigModule(Config.getFixedConfig(new SystemConfiguration())));
                install(new LifecycleModule(ServiceDiscoveryLifecycle.class));
                install(new NessJacksonModule());
                install(new HttpClientModule("test"));
                install(new DiscoveryClientModule(true));
            }
        }).injectMembers(this);

        lifecycle.executeTo(LifecycleStage.START_STAGE);
    }

    @Test
    public void testStaticAnnounce() throws Exception {
        final String announceBase = serverBase + "/announcement";

        assertTrue(discoveryClient.findAllServiceInformation().isEmpty());

        final TypeReference<Map<String, List<ServiceInformation>>> responseType = new TypeReference<Map<String, List<ServiceInformation>>>() {
        };

        Map<String, List<ServiceInformation>> announcements = httpClient
                .get(announceBase, JsonContentConverter.getResponseHandler(responseType, objectMapper)).perform();

        assertTrue(announcements.get("results").isEmpty());

        final ContentResponseHandler<HttpResponse> handler = ContentResponseHandler
                .forConverter(new HttpResponseContentConverter());

        final HttpResponse response = httpClient.post(announceBase, handler)
                .setContentType(MediaType.APPLICATION_JSON)
                .setContent(objectMapper.writeValueAsBytes(
                        ImmutableMap.of("name", "testing", "scheme", "http", "address", "localhost", "port", 8080)))
                .perform();

        assertEquals(response.getBodyAsString(), 201, response.getStatusCode());

        int tries = 20;
        ServiceInformation si = null;

        while (true) {
            try {
                si = discoveryClient.findServiceInformation("testing", null);
                break;
            } catch (final ServiceNotAvailableException e) {
            }

            if (tries-- == 0) {
                fail("Announcement never showed up");
            }

            Thread.sleep(100); // Ensure that we get some ZK ticks
        }
        LOG.info("=== Found 'testing'");
        assertNotNull(si);
        assertTrue(si.isStaticAnnouncement());
        assertEquals("8080", si.getProperty(ServiceInformation.PROP_SERVICE_PORT));
        final String location = Iterables.getOnlyElement(response.getHeaders().get(HttpHeaders.LOCATION));
        assertTrue(location.endsWith(si.getServiceId().toString()));

        Thread.sleep(500); // The DiscoveryClient in the server takes yet more time to catch up
        LOG.info("=== Read HTTP services");

        announcements = httpClient
                .get(announceBase, JsonContentConverter.getResponseHandler(responseType, objectMapper)).perform();

        assertEquals(ImmutableMap.of("results", ImmutableList.of(si)), announcements);

        httpClient.delete(location, Valid2xxContentConverter.DEFAULT_FAILING_RESPONSE_HANDLER).perform();

        tries = 20;
        while (true) {
            if (discoveryClient.findAllServiceInformation().isEmpty()) {
                break;
            }
            tries--;
            if (tries-- == 0) {
                fail("Announcement never disappeared");
            }

            Thread.sleep(100); // Ensure that we get some ZK ticks
        }
    }

    @After
    public void shutdown() {
        if (lifecycle != null) {
            lifecycle.executeTo(LifecycleStage.STOP_STAGE);
        }

        if (server != null) {
            server.stopServer();
        }
    }

    private static final int findUnusedPort() {
        int port;

        ServerSocket socket = null;
        try {
            socket = new ServerSocket();
            socket.bind(new InetSocketAddress(0));
            port = socket.getLocalPort();
        } catch (final IOException ioe) {
            throw Throwables.propagate(ioe);
        } finally {
            try {
                socket.close();
            } catch (final IOException ioe) {
                // GNDN
            }
        }

        return port;
    }
}