net.officefloor.plugin.socket.server.http.request.HttpRequestTest.java Source code

Java tutorial

Introduction

Here is the source code for net.officefloor.plugin.socket.server.http.request.HttpRequestTest.java

Source

/*
 * OfficeFloor - http://www.officefloor.net
 * Copyright (C) 2005-2013 Daniel Sagenschneider
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.officefloor.plugin.socket.server.http.request;

import java.io.File;
import java.io.FileInputStream;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import net.officefloor.frame.test.AbstractOfficeConstructTestCase;
import net.officefloor.frame.test.MockTeamSource;
import net.officefloor.frame.test.ReflectiveWorkBuilder;
import net.officefloor.frame.test.ReflectiveWorkBuilder.ReflectiveTaskBuilder;
import net.officefloor.plugin.socket.server.http.HttpTestUtil;
import net.officefloor.plugin.socket.server.http.request.config.CommunicationConfig;
import net.officefloor.plugin.socket.server.http.request.config.HeaderConfig;
import net.officefloor.plugin.socket.server.http.request.config.ProcessConfig;
import net.officefloor.plugin.socket.server.http.request.config.RequestConfig;
import net.officefloor.plugin.socket.server.http.request.config.ResponseConfig;
import net.officefloor.plugin.socket.server.http.request.config.RunConfig;
import net.officefloor.plugin.socket.server.http.server.HttpServicerBuilder;
import net.officefloor.plugin.socket.server.http.server.HttpServicerTask;
import net.officefloor.plugin.socket.server.http.server.MockHttpServer;
import net.officefloor.plugin.xml.XmlUnmarshaller;
import net.officefloor.plugin.xml.unmarshall.tree.TreeXmlUnmarshallerFactory;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;

/**
 * Runs requests against a started instance based on XML configuration.
 * 
 * @author Daniel Sagenschneider
 */
public class HttpRequestTest extends AbstractOfficeConstructTestCase {

    /**
     * Create the {@link TestSuite} of the tests to be run.
     * 
     * @return {@link TestSuite} of tests to be run.
     */
    public static Test suite() throws Exception {
        // Create the test suite
        TestSuite suite = new TestSuite(HttpRequestTest.class.getName());

        try {

            // Create an instance of the test to obtain test methods
            HttpRequestTest util = new HttpRequestTest(null, null, null, false, null);

            // Obtain the file containing XML Unmarshaller configuration
            File unmarshallerConfigFile = util.findFile(HttpRequestTest.class, "UnmarshallConfiguration.xml");

            // Obtain the current directory
            XmlUnmarshaller unmarshaller = TreeXmlUnmarshallerFactory.getInstance()
                    .createUnmarshaller(new FileInputStream(unmarshallerConfigFile));

            // Create the HTTP servicer builder
            HttpServicerBuilder httpServicerBuilder = new HttpServicerBuilder() {
                @Override
                public HttpServicerTask buildServicer(String managedObjectName, MockHttpServer server)
                        throws Exception {
                    // Register team to do the work
                    server.constructTeam("WORKER", MockTeamSource.createOnePersonTeam("WORKER"));

                    // Register the work to process messages
                    ReflectiveWorkBuilder workBuilder = server.constructWork(new RequestWork(), "servicer",
                            "service");
                    ReflectiveTaskBuilder taskBuilder = workBuilder.buildTask("service", "WORKER");
                    taskBuilder.buildObject(managedObjectName);

                    // Return the reference to the service task
                    return new HttpServicerTask("servicer", "service");
                }
            };

            // Load the non-secure tests
            final MockHttpServer httpServer = new MockHttpServer() {
            };
            loadTests("http", unmarshallerConfigFile.getParentFile(), unmarshaller, httpServer, false,
                    httpServicerBuilder, suite);

            // Load the secure tests
            final MockHttpServer httpsServer = new MockHttpServer() {
            };
            httpsServer.setupSecure();
            loadTests("https", unmarshallerConfigFile.getParentFile(), unmarshaller, httpsServer, true,
                    httpServicerBuilder, suite);

            // Add a task to shutdown the servers
            suite.addTest(new TestCase("Shutdown HTTP Server") {
                @Override
                protected void runTest() throws Throwable {
                    httpServer.shutdown();
                    httpsServer.shutdown();
                }
            });

        } catch (Throwable ex) {
            // Add warning that failed to setup
            suite.addTest(TestSuite.warning("Failed setting up suite of tests: " + ex.getMessage() + " ["
                    + ex.getClass().getSimpleName() + "]"));
        }

        // Return the test suite
        return suite;
    }

    /**
     * Loads the tests for the *Test.xml files.
     * 
     * @param testNamePrefix
     *            Prefix for the test name.
     * @param directory
     *            Directory to search for tests.
     * @param unmarshaller
     *            {@link XmlUnmarshaller} to unmarshal the test.
     * @param server
     *            {@link MockHttpServer}.
     * @param isSecure
     *            Indicates if to be secure.
     * @param httpServicerBuilder
     *            {@link HttpServicerBuilder}.
     * @param suite
     *            {@link TestSuite} to add the tests.
     */
    private static void loadTests(String testNamePrefix, File directory, XmlUnmarshaller unmarshaller,
            MockHttpServer server, boolean isSecure, HttpServicerBuilder httpServicerBuilder, TestSuite suite)
            throws Exception {

        // Obtain the tests
        for (File file : directory.listFiles()) {

            // Obtain the corresponding test name for the file
            String testName = (testNamePrefix.length() == 0 ? "" : testNamePrefix + ".") + file.getName();

            // Determine if child directory
            if (file.isDirectory()) {
                // Child directory, so find tests recursively
                loadTests(testName, file, unmarshaller, server, isSecure, httpServicerBuilder, suite);

            } else {
                // File and ensure is a test file
                if (!file.getName().endsWith("Test.xml")) {
                    // Not a test file
                    continue;
                }

                // Load the configuration
                RunConfig configuration = new RunConfig();
                unmarshaller.unmarshall(new FileInputStream(file), configuration);

                // Create the test
                suite.addTest(new HttpRequestTest(testName, configuration, server, isSecure, httpServicerBuilder));
            }
        }
    }

    /**
     * {@link RunConfig}.
     */
    private final RunConfig configuration;

    /**
     * {@link MockHttpServer}.
     */
    private final MockHttpServer server;

    /**
     * Indicates if the {@link MockHttpServer} is to be secure.
     */
    private final boolean isSecure;

    /**
     * {@link HttpServicerBuilder}.
     */
    private final HttpServicerBuilder httpServicerBuilder;

    /**
     * Instantiate.
     * 
     * @param testName
     *            Name of the test.
     * @param configuration
     *            {@link RunConfig}.
     * @param server
     *            {@link MockHttpServer}.
     * @param isSecure
     *            Indicates if the {@link MockHttpServer} is to be secure.
     * @param httpServicerBuilder
     *            {@link HttpServicerBuilder}.
     */
    public HttpRequestTest(String testName, RunConfig configuration, MockHttpServer server, boolean isSecure,
            HttpServicerBuilder httpServicerBuilder) {
        this.setName(testName);
        this.configuration = configuration;
        this.server = server;
        this.isSecure = isSecure;
        this.httpServicerBuilder = httpServicerBuilder;
    }

    /*
     * ==================== TestCase =================================
     */

    @Override
    protected void runTest() throws Throwable {

        // Start the server
        this.server.startup(this.httpServicerBuilder);
        assertEquals("Incorrect secureness for server", this.isSecure, this.server.isServerSecure());

        // Validate the configuration
        assertTrue("Must have at least 1 communication", this.configuration.communications.size() > 0);
        for (CommunicationConfig communication : this.configuration.communications) {
            assertNotNull("Communication must have a request", communication.request);
            assertNotNull("Communication must have a process", communication.process);
            assertNotNull("Communication must have a response", communication.response);
        }

        // Create the HTTP Client to send requests
        HttpClient client = this.server.createHttpClient();

        System.out.println("====== " + this.getName() + " ======");

        // Run the communications
        for (CommunicationConfig communication : this.configuration.communications) {

            // Indicate the request being run
            System.out.println("--- REQUEST ---");
            RequestConfig request = communication.request;
            System.out.println(request.method + " " + request.path + " " + request.version);
            for (HeaderConfig header : request.headers) {
                System.out.println(header.name + ": " + header.value);
            }
            System.out.println("\n" + request.body);

            // Specify the configuration to service the request
            RequestWork.setConfiguration(communication);

            // Create the method
            String requestUrl = this.server.getServerUrl() + request.path;
            HttpUriRequest method;
            if ("GET".equals(request.method)) {
                method = new HttpGet(requestUrl);
            } else if ("POST".equals(request.method)) {
                HttpPost post = new HttpPost(requestUrl);
                post.setEntity(new StringEntity(request.body));
                method = post;
            } else {
                TestCase.fail("Unknown request method '" + request.method + "'");
                return;
            }

            // Provide any headers to the request
            for (HeaderConfig header : request.headers) {
                method.addHeader(header.name, header.value);
            }

            // Indicate the processing
            System.out.println("--- PROCESS ---");
            ProcessConfig process = communication.process;
            System.out.println("isClose=" + process.isClose);
            System.out.println(process.body);

            // Execute the method
            HttpResponse methodResponse = client.execute(method);

            // Obtain the response body
            String actualResponseBody = HttpTestUtil.getEntityBody(methodResponse);

            // Validate no failure in processing
            this.server.validateNoTopLevelEscalation();

            // Indicate the expected response
            ResponseConfig response = communication.response;
            System.out.println("--- EXPECTED RESPONSE (isClosed=" + response.isClosed + ") ---");
            System.out.println(response.status + " " + response.version + " " + response.message);
            for (HeaderConfig header : response.headers) {
                System.out.println(header.name + ": " + header.value);
            }
            System.out.println("\n" + response.body);

            // Indicate the actual response
            System.out.println("--- ACTUAL RESPONSE ---");
            StatusLine status = methodResponse.getStatusLine();
            System.out.println(
                    status.getStatusCode() + " " + status.getProtocolVersion() + " " + status.getReasonPhrase());
            for (Header header : methodResponse.getAllHeaders()) {
                System.out.println(header.getName() + ": " + header.getValue());
            }
            System.out.println();
            System.out.println(actualResponseBody);

            // Validate the response
            assertEquals("Incorrect response status", response.status, status.getStatusCode());
            assertEquals("Incorrect status message", response.message, status.getReasonPhrase());
            assertEquals("Incorrect response HTTP version", response.version,
                    status.getProtocolVersion().toString());
            for (HeaderConfig header : response.headers) {
                assertEquals("Incorrect response header '" + header.name + "'", header.value,
                        methodResponse.getFirstHeader(header.name).getValue());
            }
            assertEquals("Incorrect response body", response.body, actualResponseBody);
        }
    }

}