com.cinchapi.concourse.http.HttpTest.java Source code

Java tutorial

Introduction

Here is the source code for com.cinchapi.concourse.http.HttpTest.java

Source

/*
 * Copyright (c) 2013-2016 Cinchapi 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.cinchapi.concourse.http;

import java.io.IOException;
import java.lang.reflect.Type;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.cinchapi.concourse.server.ConcourseServer;
import com.cinchapi.concourse.server.http.HttpServer;
import com.cinchapi.concourse.test.ConcourseIntegrationTest;
import com.cinchapi.concourse.test.Variables;
import com.cinchapi.concourse.time.Time;
import com.cinchapi.concourse.util.Networking;
import com.cinchapi.concourse.util.Reflection;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

/**
 * A class that defines methods and basic tests for interacting with the HTTP
 * functionality of Concourse Server.
 * 
 * @author Jeff Nelson
 */
public class HttpTest extends ConcourseIntegrationTest {

    /**
     * Return the response body as the appropriate Java object.
     * 
     * @param response
     * @return the response body
     */
    protected static <T> T bodyAsJava(Response response, TypeToken<T> type) {
        Type type0 = type.getType();
        return new Gson().fromJson(bodyAsJson(response), type0);
    }

    /**
     * Return a JsonElement representation of the response body.
     * 
     * @param response
     * @param the json response
     */
    protected static JsonElement bodyAsJson(Response response) {
        try {
            String body = response.body().string();
            JsonElement json = new JsonParser().parse(body);
            Variables.register("json_body_" + response.hashCode(), body);
            return json;
        } catch (IOException e) {
            throw Throwables.propagate(e);
        }
    }

    /**
     * Do anything that is necessary to clean up the URL args. For example, make
     * sure any records (represented as an int or long) does not get rendered
     * using comma separators.
     * 
     * @param args
     * @return the clean args
     */
    private static Object[] cleanUrlArgs(Object... args) {
        for (int i = 0; i < args.length; i++) {
            Object arg = args[i];
            if (arg.getClass() == long.class || arg.getClass() == int.class) {
                args[i] = Long.toString((long) arg);
            } else if (arg.getClass() == Long.class || arg.getClass() == Integer.class) {
                args[i] = arg.toString();
            }
        }
        return args;
    }

    /**
     * Go through the {@code args} and filter out any that shouldn't be
     * considered URL args. It is possible that some of the filtered args will
     * be passed as arguments to the {@code builder}.
     * 
     * @param builder
     * @param args
     * @return the filtered args
     */
    private static Object[] filterArgs(Request.Builder builder, Object... args) {
        List<Object> argsList = Lists.newArrayList(args);
        Iterator<Object> it = argsList.iterator();
        while (it.hasNext()) {
            Object arg = it.next();
            if (arg instanceof Headers) {
                builder.headers((Headers) arg);
                it.remove();
            }
        }
        args = argsList.size() != args.length ? argsList.toArray() : args;
        return args;
    }

    /**
     * JSON media type
     */
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    /**
     * The base URL.
     */
    private String base = "http://localhost:";

    /**
     * The HTTP Client.
     */
    private OkHttpClient http = new OkHttpClient();

    /**
     * A reference to the HttpServer that interacts with Concourse Server.
     * Subclasses should never need to interact with this directly.
     */
    private HttpServer httpServer;

    {
        // Setup support for cookies
        CookieManager cm = new CookieManager();
        cm.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        http.setCookieHandler(cm);
    }

    @Override
    public void afterEachTest() {
        httpServer.stop();
        clearClientCookies();
    }

    @Override
    public void beforeEachTest() {
        int port = Networking.getOpenPort();
        httpServer = HttpServer.create(Reflection.<ConcourseServer>get("server", this), port);
        httpServer.start();
        // Wait for the HTTP server to start
        Request req = new Request.Builder().url(base).head().build();
        long start = Time.now();
        boolean escape = false;
        while (!escape) {
            try {
                http.newCall(req).execute();
                escape = true;
            } catch (IOException e) {
                escape = TimeUnit.SECONDS.convert(Time.now() - start, TimeUnit.MICROSECONDS) > 5;
            }
        }
        base += port;
    }

    /**
     * Remove all the client side cookies.
     * 
     * @return {@code true} if the cookies are removed
     */
    protected boolean clearClientCookies() {
        return ((CookieManager) http.getCookieHandler()).getCookieStore().removeAll();
    }

    /**
     * Perform a DELETE request
     * 
     * @param route
     * @param args - include a {@link Headers} object to set the request headers
     * @return the response
     */
    protected Response delete(String route, Object... args) {
        try {
            Request.Builder builder = new Request.Builder();
            args = filterArgs(builder, args);
            args = cleanUrlArgs(args);
            route = MessageFormat.format(route, args);
            Request request = builder.url(base + route).delete().build();
            Response response = http.newCall(request).execute();
            long ts = response.hashCode();
            Variables.register("request_" + ts, request);
            Variables.register("response_" + ts, response);
            return response;
        } catch (IOException e) {
            throw Throwables.propagate(e);
        }
    }

    /**
     * Perform a GET request
     * 
     * @param route
     * @param args - include a {@link Headers} object to set the request headers
     * @return the response
     */
    protected Response get(String route, Object... args) {
        try {
            Request.Builder builder = new Request.Builder();
            args = filterArgs(builder, args);
            args = cleanUrlArgs(args);
            route = MessageFormat.format(route, args);
            Request request = builder.url(base + route).get().build();
            Response response = http.newCall(request).execute();
            long ts = response.hashCode();
            Variables.register("request_" + ts, request);
            Variables.register("response_" + ts, response);
            return response;
        } catch (IOException e) {
            throw Throwables.propagate(e);
        }
    }

    /**
     * Perform a login request to the default environment.
     * 
     * @return the response
     */
    protected Response login() {
        return login("");
    }

    /**
     * Perform a login request.
     * 
     * @param environment
     * @return the response
     */
    protected Response login(String environment) {
        environment = Strings.isNullOrEmpty(environment) ? "" : "/" + environment;
        JsonObject creds = new JsonObject();
        creds.addProperty("username", "admin");
        creds.addProperty("password", "admin");
        Response resp = post(environment + "/login", creds.toString());
        return resp;
    }

    /**
     * Perform a POST request.
     * 
     * @param route
     * @param data
     * @param args - include a {@link Headers} object to set the request headers
     * @return the response
     */
    protected Response post(String route, String data, Object... args) {
        try {
            RequestBody body = RequestBody.create(JSON, data);
            Request.Builder builder = new Request.Builder();
            args = filterArgs(builder, args);
            args = cleanUrlArgs(args);
            route = MessageFormat.format(route, args);
            Request request = builder.url(base + route).post(body).build();
            Response response = http.newCall(request).execute();
            long ts = response.hashCode();
            Variables.register("request_" + ts, request);
            Variables.register("response_" + ts, response);
            return response;
        } catch (IOException e) {
            throw Throwables.propagate(e);
        }
    }

    /**
     * Perform a PUT request.
     * 
     * @param route
     * @param data
     * @param args - include a {@link Headers} object to set the request headers
     * @return the response
     */
    protected Response put(String route, String data, Object... args) {
        try {
            RequestBody body = RequestBody.create(JSON, data);
            Request.Builder builder = new Request.Builder();
            args = filterArgs(builder, args);
            args = cleanUrlArgs(args);
            route = MessageFormat.format(route, args);
            Request request = builder.url(base + route).put(body).build();
            Response response = http.newCall(request).execute();
            long ts = response.hashCode();
            Variables.register("request_" + ts, request);
            Variables.register("response_" + ts, response);
            return response;
        } catch (IOException e) {
            throw Throwables.propagate(e);
        }
    }

}