org.metaeffekt.dcc.agent.DccAgentTest.java Source code

Java tutorial

Introduction

Here is the source code for org.metaeffekt.dcc.agent.DccAgentTest.java

Source

/**
 * Copyright 2009-2017 the original author or authors.
 *
 * 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.metaeffekt.dcc.agent;

import static org.metaeffekt.dcc.commons.commands.Commands.CLEAN;
import static org.metaeffekt.dcc.commons.commands.Commands.CONFIGURE;
import static org.metaeffekt.dcc.commons.commands.Commands.INITIALIZE;
import static org.metaeffekt.dcc.commons.commands.Commands.INSTALL;
import static org.metaeffekt.dcc.commons.commands.Commands.LOGS;
import static org.metaeffekt.dcc.commons.commands.Commands.STATE;
import static org.metaeffekt.dcc.commons.commands.Commands.VERSION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.metaeffekt.dcc.commons.DccConstants;
import org.metaeffekt.dcc.commons.domain.Id;
import org.metaeffekt.dcc.commons.domain.Type.DeploymentId;
import org.metaeffekt.dcc.commons.domain.Type.PackageId;
import org.metaeffekt.dcc.commons.domain.Type.UnitId;

/**
 * @author Alexander D.
 * @author Jochen K.
 */
public class DccAgentTest {

    private static final Logger LOG = LoggerFactory.getLogger(DccAgentTest.class);

    private static final String HOST = "localhost";

    private static final long STARTUP_TIMEOUT = 30000;

    private static final int NETWORK_TIMEOUT = 3000000;

    private static final Id<DeploymentId> DEPLOYMENT_ID = Id.createDeploymentId("phm");

    private static final Id<PackageId> PACKAGE_ID = Id.createPackageId("somePackageId");

    private static final Id<UnitId> UNIT_ID = Id.createUnitId("someUnitId");

    private static DccAgent agent;

    private static int port;

    private HttpClient httpClient;

    private UnitBasedEndpointUriBuilder unitBasedEndpointUriBuilder;

    private DeploymentBasedEndpointUriBuilder deploymentBasedEndpointUriBuilder;

    private HostBasedEndpointUriBuilder hostBasedEndpointUriBuilder;

    private byte[] executionProperties = "somePropertyKey=somePropertyValue".getBytes();

    private Map<String, byte[]> properties = new HashMap<String, byte[]>();

    @BeforeClass
    public static void startup() throws BindException {

        port = findAvailablePort();

        startAgent();

    }

    @AfterClass
    public static void shutdown() throws Exception {
        agent.stop();
    }

    @Before
    public void setUp() throws IOException, GeneralSecurityException {
        properties.put(DccConstants.COMMAND_PROPERTIES, executionProperties);

        this.unitBasedEndpointUriBuilder = (UnitBasedEndpointUriBuilder) new UnitBasedEndpointUriBuilder()
                .withHost(HOST).withPort(port).withTimeout(NETWORK_TIMEOUT);
        this.deploymentBasedEndpointUriBuilder = (DeploymentBasedEndpointUriBuilder) new DeploymentBasedEndpointUriBuilder()
                .withHost(HOST).withPort(port).withTimeout(NETWORK_TIMEOUT);
        this.hostBasedEndpointUriBuilder = (HostBasedEndpointUriBuilder) new HostBasedEndpointUriBuilder()
                .withHost(HOST).withPort(port).withTimeout(NETWORK_TIMEOUT);

        httpClient = newHttpClient();
        File configTargetDir = new File("target/opt");
        FileUtils.deleteQuietly(configTargetDir);
        FileUtils.forceMkdir(configTargetDir);

        File tmpTargetDir = new File("target/tmp/");
        FileUtils.deleteQuietly(tmpTargetDir);
        FileUtils.forceMkdir(tmpTargetDir);
    }

    @Test
    public void cleanInitializeInstallAndConfigure() throws URISyntaxException, IOException, InterruptedException {

        HttpResponse response = httpClient
                .execute(deploymentBasedEndpointUriBuilder.buildHttpUriRequest(STATE, DEPLOYMENT_ID));
        assertEquals("GET STATE failed", 200, response.getStatusLine().getStatusCode());
        assertEquals(0, getStates(response).size());

        response = httpClient.execute(deploymentBasedEndpointUriBuilder.buildHttpUriRequest(CLEAN, DEPLOYMENT_ID));
        assertEquals("CLEAN failed", 200, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        response = httpClient.execute(deploymentBasedEndpointUriBuilder.buildHttpUriRequest(INITIALIZE,
                DEPLOYMENT_ID, new FileEntity(new File("src/test/resources/test.zip"))));
        assertEquals("INITIALIZE failed", 200, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        response = httpClient.execute(unitBasedEndpointUriBuilder.buildHttpUriRequest(INSTALL, DEPLOYMENT_ID,
                UNIT_ID, PACKAGE_ID, properties));
        assertEquals("INSTALL failed", 200, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        response = httpClient.execute(unitBasedEndpointUriBuilder.buildHttpUriRequest(CONFIGURE, DEPLOYMENT_ID,
                UNIT_ID, PACKAGE_ID, properties));
        assertEquals("CONFIGURE failed", 200, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        response = httpClient.execute(deploymentBasedEndpointUriBuilder.buildHttpUriRequest(STATE, DEPLOYMENT_ID));
        assertEquals("GET STATE failed", 200, response.getStatusLine().getStatusCode());
        Set<String> states = getStates(response);
        assertEquals(3, states.size());
        assertTrue("Does not contain " + INITIALIZE.toString(), states.contains(INITIALIZE.toString()));
        assertTrue("Does not contain " + UNIT_ID + "/" + INSTALL.toString(),
                states.contains(UNIT_ID + "/" + INSTALL.toString()));
        assertTrue("Does not contain " + UNIT_ID + "/" + CONFIGURE.toString(),
                states.contains(UNIT_ID + "/" + CONFIGURE.toString()));

    }

    @Test
    public void getLogs() throws IOException {
        HttpResponse response = httpClient.execute(hostBasedEndpointUriBuilder.buildHttpUriRequest(LOGS));
        assertEquals("Expected Http 404 Bad Request", 404, response.getStatusLine().getStatusCode());
    }

    @Test
    public void sendEmptyPayload() throws URISyntaxException, ClientProtocolException, IOException {
        HttpResponse response = httpClient
                .execute(deploymentBasedEndpointUriBuilder.buildHttpUriRequest(INITIALIZE, DEPLOYMENT_ID, null));
        assertEquals("Expected Http 400 Bad Request", 400, response.getStatusLine().getStatusCode());
    }

    @Test
    public void getVersion() throws URISyntaxException, ClientProtocolException, IOException {

        HttpResponse response = httpClient.execute(hostBasedEndpointUriBuilder.buildHttpUriRequest(VERSION));

        assertEquals("GET VERSION failed", 200, response.getStatusLine().getStatusCode());

        try (InputStream content = response.getEntity().getContent();
                ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            IOUtils.copy(content, bos);
            assertEquals("1.4.0", bos.toString());
        }

    }

    @Test
    public void state() throws URISyntaxException, ClientProtocolException, IOException {

        HttpResponse response = httpClient
                .execute(deploymentBasedEndpointUriBuilder.buildHttpUriRequest(STATE, DEPLOYMENT_ID));
        assertEquals("GET STATE failed", 200, response.getStatusLine().getStatusCode());
        assertEquals(0, getStates(response).size());

    }

    private Set<String> getStates(HttpResponse response) throws IOException {

        Set<String> states = new HashSet<>();

        try (ZipInputStream zipStream = new ZipInputStream(response.getEntity().getContent());) {

            ZipEntry zipEntry = zipStream.getNextEntry();

            while (zipEntry != null) {
                String name = zipEntry.getName();
                name = name.substring(0, name.lastIndexOf("."));
                states.add(name);
                if (zipStream.available() > 0) {
                    zipEntry = zipStream.getNextEntry();
                }
            }
        } finally {
            EntityUtils.consume(response.getEntity());
        }

        return states;
    }

    private static void startAgent() {

        agent = new DccAgent(port);

        ExecutorService executorService = Executors.newSingleThreadExecutor();

        final long begin = System.currentTimeMillis();

        executorService.execute(new Runnable() {

            @Override
            public void run() {
                try {
                    agent.start();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });

        LOG.info("Waiting for agent to start");
        while (!agent.isStarted()) {

            if (System.currentTimeMillis() - begin > STARTUP_TIMEOUT) {
                throw new IllegalStateException("Failed to start agent. Timeout expired.");
            }

            try {
                Thread.sleep(500);
                LOG.info(".");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        LOG.info("");
        LOG.info("Agent is started");
    }

    private HttpClient newHttpClient() throws GeneralSecurityException, IOException {
        final char[] password = "changeit".toCharArray();

        final KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(DccAgentTest.class.getResourceAsStream("/client.keystore"), password);

        final KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(DccAgentTest.class.getResourceAsStream("/client.truststore"), password);

        final SSLContextBuilder sslContextBuilder = SSLContexts.custom();
        sslContextBuilder.loadKeyMaterial(keyStore, password);
        sslContextBuilder.loadTrustMaterial(trustStore);

        final HttpClientBuilder builder = HttpClientBuilder.create();
        builder.setSslcontext(sslContextBuilder.build());
        builder.setHostnameVerifier(new AllowAllHostnameVerifier());

        final HttpClient client = builder.build();
        return client;
    }

    private static int findAvailablePort() throws BindException {

        for (int p = DccAgentEndpoint.DEFAULT_PORT; p < 65535; p++) {

            try {
                new ServerSocket(p);
                return p;
            } catch (IOException e) {
            }
        }

        throw new BindException("unable to find an available port");

    }

}