/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* 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.asakusafw.yaess.jobqueue.client;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URL;
import java.util.HashMap;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.entity.StringEntity;
import org.apache.http.localserver.LocalTestServer;
import org.apache.http.localserver.RequestBasicAuth;
import org.apache.http.localserver.ResponseBasicUnauthorized;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.http.util.EntityUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.asakusafw.yaess.core.ExecutionPhase;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* Test for {@link HttpJobClient}.
*/
public class HttpJobClientTest {
static final Logger LOG = LoggerFactory.getLogger(HttpJobClientTest.class);
private LocalTestServer server;
private String baseUrl;
/**
* Initializes the test.
* @throws Exception if some errors were occurred
*/
@Before
public void setUp() throws Exception {
BasicHttpProcessor proc = new BasicHttpProcessor();
proc.addInterceptor(new ResponseDate());
proc.addInterceptor(new ResponseServer());
proc.addInterceptor(new ResponseContent());
proc.addInterceptor(new ResponseConnControl());
proc.addInterceptor(new RequestBasicAuth());
proc.addInterceptor(new ResponseBasicUnauthorized());
server = new LocalTestServer(proc, null);
server.start();
InetSocketAddress address = server.getServiceAddress();
baseUrl = new URL("http", address.getHostName(), address.getPort(), "/").toExternalForm();
}
/**
* Cleans up the test.
* @throws Exception if some errors were occurred
*/
@After
public void tearDown() throws Exception {
server.stop();
}
/**
* register.
* @throws Exception if failed
*/
@Test
public void register() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "initialized");
result.addProperty("jrid", "testing");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
JobScript script = new JobScript();
script.setBatchId("b");
script.setFlowId("f");
script.setExecutionId("e");
script.setPhase(ExecutionPhase.MAIN);
script.setStageId("s");
script.setMainClassName("Cls");
script.setProperties(new HashMap<String, String>());
script.setEnvironmentVariables(new HashMap<String, String>());
JobId id = client.register(script);
assertThat(id, is(new JobId("testing")));
assertThat(handler.requestElement, is(notNullValue()));
JsonObject object = handler.requestElement;
assertThat(object.get("batchId").getAsString(), is("b"));
assertThat(object.get("flowId").getAsString(), is("f"));
assertThat(object.get("executionId").getAsString(), is("e"));
assertThat(object.get("phaseId").getAsString(), is("main"));
assertThat(object.get("stageId").getAsString(), is("s"));
assertThat(object.get("properties").isJsonObject(), is(true));
assertThat(object.get("env").isJsonObject(), is(true));
}
/**
* register error.
* @throws Exception if failed
*/
@Test
public void register_error() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "error");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
JobScript script = new JobScript();
script.setBatchId("b");
script.setFlowId("f");
script.setPhase(ExecutionPhase.MAIN);
script.setStageId("s");
script.setExecutionId("e");
script.setMainClassName("Cls");
script.setProperties(new HashMap<String, String>());
script.setEnvironmentVariables(new HashMap<String, String>());
try {
client.register(script);
fail();
} catch (IOException e) {
LOG.debug("OK.", e);
}
assertThat(handler.requestElement, is(notNullValue()));
}
/**
* register.
* @throws Exception if failed
*/
@Test
public void register_missing() throws Exception {
ErrorHandler handler = new ErrorHandler(404, null);
server.register("/jobs", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
JobScript script = new JobScript();
script.setBatchId("b");
script.setFlowId("f");
script.setPhase(ExecutionPhase.MAIN);
script.setStageId("s");
script.setExecutionId("e");
script.setMainClassName("Cls");
script.setProperties(new HashMap<String, String>());
script.setEnvironmentVariables(new HashMap<String, String>());
try {
client.register(script);
fail();
} catch (IOException e) {
LOG.debug("OK.", e);
}
assertThat(handler.requestElement, is(notNullValue()));
}
/**
* register.
* @throws Exception if failed
*/
@Test
public void register_no_connections() throws Exception {
server.stop();
HttpJobClient client = new HttpJobClient(baseUrl);
JobScript script = new JobScript();
script.setBatchId("b");
script.setFlowId("f");
script.setPhase(ExecutionPhase.MAIN);
script.setStageId("s");
script.setExecutionId("e");
script.setMainClassName("Cls");
script.setProperties(new HashMap<String, String>());
script.setEnvironmentVariables(new HashMap<String, String>());
try {
client.register(script);
fail();
} catch (IOException e) {
LOG.debug("OK.", e);
}
}
/**
* register.
* @throws Exception if failed
*/
@Test
public void register_auth() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "initialized");
result.addProperty("jrid", "testing");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs", new AuthHandler(handler));
HttpJobClient client = new HttpJobClient(baseUrl, "a", "b");
JobScript script = new JobScript();
script.setBatchId("b");
script.setFlowId("f");
script.setExecutionId("e");
script.setPhase(ExecutionPhase.MAIN);
script.setStageId("s");
script.setMainClassName("Cls");
script.setProperties(new HashMap<String, String>());
script.setEnvironmentVariables(new HashMap<String, String>());
client.register(script);
}
/**
* register.
* @throws Exception if failed
*/
@Test
public void register_unauth() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "initialized");
result.addProperty("jrid", "testing");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs", new AuthHandler(handler));
HttpJobClient client = new HttpJobClient(baseUrl);
JobScript script = new JobScript();
script.setBatchId("b");
script.setFlowId("f");
script.setExecutionId("e");
script.setPhase(ExecutionPhase.MAIN);
script.setStageId("s");
script.setMainClassName("Cls");
script.setProperties(new HashMap<String, String>());
script.setEnvironmentVariables(new HashMap<String, String>());
try {
client.register(script);
fail();
} catch (IOException e) {
// ok.
LOG.debug("OK.", e);
}
}
/**
* status (initialized).
* @throws Exception if failed
*/
@Test
public void status_initialized() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "initialized");
result.addProperty("jrid", "testing");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs/testing", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
JobStatus status = client.getStatus(new JobId("testing"));
assertThat(status.getKind(), is(JobStatus.Kind.INITIALIZED));
assertThat(handler.requestElement, is(nullValue()));
}
/**
* status (waiting).
* @throws Exception if failed
*/
@Test
public void status_waiting() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "waiting");
result.addProperty("jrid", "testing");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs/testing", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
JobStatus status = client.getStatus(new JobId("testing"));
assertThat(status.getKind(), is(JobStatus.Kind.WAITING));
assertThat(handler.requestElement, is(nullValue()));
}
/**
* status (running).
* @throws Exception if failed
*/
@Test
public void status_running() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "running");
result.addProperty("jrid", "testing");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs/testing", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
JobStatus status = client.getStatus(new JobId("testing"));
assertThat(status.getKind(), is(JobStatus.Kind.RUNNING));
assertThat(handler.requestElement, is(nullValue()));
}
/**
* status (completed).
* @throws Exception if failed
*/
@Test
public void status_completed() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "completed");
result.addProperty("jrid", "testing");
result.addProperty("exitCode", "1");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs/testing", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
JobStatus status = client.getStatus(new JobId("testing"));
assertThat(status.getKind(), is(JobStatus.Kind.COMPLETED));
assertThat(status.getExitCode(), is(Integer.valueOf(1)));
assertThat(handler.requestElement, is(nullValue()));
}
/**
* status (error).
* @throws Exception if failed
*/
@Test
public void status_error() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "error");
result.addProperty("jrid", "testing");
result.addProperty("message", "ERROR");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs/testing", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
JobStatus status = client.getStatus(new JobId("testing"));
assertThat(status.getKind(), is(JobStatus.Kind.ERROR));
assertThat(handler.requestElement, is(nullValue()));
}
/**
* status (exception occurred).
* @throws Exception if failed
*/
@Test
public void status_missing() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "initialized");
result.addProperty("jrid", "testing");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs/testing", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
try {
client.getStatus(new JobId("other"));
fail();
} catch (IOException e) {
// ok.
}
}
/**
* submit.
* @throws Exception if failed
*/
@Test
public void submit() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "waiting");
result.addProperty("jrid", "testing");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs/testing/execute", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
client.submit(new JobId("testing"));
assertThat(handler.requestElement, is(nullValue()));
}
/**
* submit.
* @throws Exception if failed
*/
@Test
public void submit_error() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "error");
result.addProperty("message", "ERROR");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs/testing/execute", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
try {
client.submit(new JobId("testing"));
fail();
} catch (IOException e) {
// ok.
}
assertThat(handler.requestElement, is(nullValue()));
}
/**
* submit.
* @throws Exception if failed
*/
@Test
public void submit_missing() throws Exception {
JsonObject result = new JsonObject();
result.addProperty("status", "waiting");
result.addProperty("jrid", "other");
JsonHandler handler = new JsonHandler(result);
server.register("/jobs/testing/execute", handler);
HttpJobClient client = new HttpJobClient(baseUrl);
try {
client.submit(new JobId("other"));
fail();
} catch (IOException e) {
// ok.
}
assertThat(handler.requestElement, is(nullValue()));
}
static JsonElement parse(String content) {
return new JsonParser().parse(content);
}
private static class JsonHandler implements HttpRequestHandler {
final JsonElement responseElement;
volatile JsonObject requestElement;
public JsonHandler(JsonElement element) {
this.responseElement = element;
}
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
response.setStatusCode(200);
response.setEntity(new StringEntity(
new Gson().toJson(responseElement).toString(), HttpJobClient.CONTENT_TYPE));
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
String content = EntityUtils.toString(entity, "UTF-8");
JsonElement element = parse(content);
if (element instanceof JsonObject) {
requestElement = (JsonObject) element;
}
}
}
}
private static class AuthHandler implements HttpRequestHandler {
private final HttpRequestHandler delegate;
public AuthHandler(HttpRequestHandler delegate) {
this.delegate = delegate;
}
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
String credentials = (String) context.getAttribute("creds");
if (credentials == null || credentials.equals("a:b") == false) {
response.setStatusCode(HttpStatus.SC_UNAUTHORIZED);
} else {
delegate.handle(request, response, context);
}
}
}
private static class ErrorHandler implements HttpRequestHandler {
private final int status;
private final String code;
volatile JsonObject requestElement;
public ErrorHandler(int status, String code) {
this.status = status;
this.code = code;
}
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
response.setStatusCode(status);
if (code != null) {
JsonObject object = new JsonObject();
object.addProperty("error", code);
object.addProperty("message", code);
response.setEntity(new StringEntity(new Gson().toJson(object).toString(), HttpJobClient.CONTENT_TYPE));
}
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
String content = EntityUtils.toString(entity, "UTF-8");
JsonElement element = parse(content);
if (element instanceof JsonObject) {
requestElement = (JsonObject) element;
}
}
}
}
}