package org.kairosdb.core.http.rest;
import ch.qos.logback.classic.Level;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import com.google.gson.GsonBuilder;
import org.junit.Before;
import org.junit.Test;
import org.kairosdb.core.aggregator.TestAggregatorFactory;
import org.kairosdb.core.exception.KairosDBException;
import org.kairosdb.core.groupby.TestGroupByFactory;
import org.kairosdb.core.http.rest.json.ErrorResponse;
import org.kairosdb.core.http.rest.json.QueryParser;
import org.kairosdb.core.http.rest.json.RollupResponse;
import org.kairosdb.core.http.rest.json.TestQueryPluginFactory;
import org.kairosdb.rollup.RollUpException;
import org.kairosdb.rollup.RollUpTasksStore;
import org.kairosdb.rollup.RollupTask;
import org.kairosdb.util.LoggingUtils;
import org.mockito.ArgumentCaptor;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static javax.ws.rs.core.Response.Status.*;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.core.IsNot.not;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
public class RollUpResourceTest
{
private static final String BEAN_VALIDATION_ERROR = "bean validation error";
private static final String CONTEXT = "context";
private static final String INTERNAL_EXCEPTION_MESSAGE = "Internal Exception";
private RollUpResource resource;
private RollUpTasksStore mockStore;
private QueryParser mockQueryParser;
private QueryParser queryParser;
@Before
public void setup() throws KairosDBException
{
mockStore = mock(RollUpTasksStore.class);
mockQueryParser = mock(QueryParser.class);
queryParser = new QueryParser(new TestAggregatorFactory(),
new TestGroupByFactory(), new TestQueryPluginFactory());
resource = new RollUpResource(mockQueryParser, mockStore);
}
@Test(expected = NullPointerException.class)
public void testCreate_nullJsonInvalid()
{
resource.create(null);
}
@Test(expected = IllegalArgumentException.class)
public void testCreate_emptyJsonInvalid()
{
resource.create("");
}
@Test
public void testCreate_parseError() throws IOException, QueryException
{
when(mockQueryParser.parseRollupTask(anyString())).thenThrow(createBeanException());
Response response = resource.create("thejson");
ErrorResponse errorResponse = (ErrorResponse) response.getEntity();
assertThat(response.getStatus(), equalTo(BAD_REQUEST.getStatusCode()));
assertThat(errorResponse.getErrors().size(), equalTo(1));
assertThat(errorResponse.getErrors().get(0), equalTo(getBeanValidationMessage()));
}
@Test
public void testCreate_internalError() throws IOException, QueryException
{
Level previousLogLevel = LoggingUtils.setLogLevel(Level.OFF);
try
{
when(mockQueryParser.parseRollupTask(anyString())).thenThrow(createQueryException());
Response response = resource.create("thejson");
ErrorResponse errorResponse = (ErrorResponse) response.getEntity();
assertThat(response.getStatus(), equalTo(INTERNAL_SERVER_ERROR.getStatusCode()));
assertThat(errorResponse.getErrors().size(), equalTo(1));
assertThat(errorResponse.getErrors().get(0), equalTo(INTERNAL_EXCEPTION_MESSAGE));
}
finally
{
LoggingUtils.setLogLevel(previousLogLevel);
}
}
@Test
public void testCreate() throws IOException, QueryException
{
resource = new RollUpResource(queryParser, mockStore);
String json = Resources.toString(Resources.getResource("rolluptask1.json"), Charsets.UTF_8);
RollupTask task = queryParser.parseRollupTask(json);
Response response = resource.create(json);
assertThat(response.getStatus(), equalTo(OK.getStatusCode()));
assertRollupResponse((String) response.getEntity(), task);
}
@Test
public void testList() throws IOException, QueryException, RollUpException
{
resource = new RollUpResource(queryParser, mockStore);
String json = Resources.toString(Resources.getResource("rolluptasks.json"), Charsets.UTF_8);
List<RollupTask> tasks = queryParser.parseRollupTasks(json);
when(mockStore.read()).thenReturn(tasks);
Response response = resource.list();
List<RollupTask> responseTasks = queryParser.parseRollupTasks((String) response.getEntity());
assertThat(response.getStatus(), equalTo(OK.getStatusCode()));
assertThat(responseTasks, containsInAnyOrder(tasks.toArray()));
}
@Test
public void testList_internalError() throws IOException, QueryException, RollUpException
{
Level previousLogLevel = LoggingUtils.setLogLevel(Level.OFF);
try
{
when(mockStore.read()).thenThrow(createRollupException());
Response response = resource.list();
ErrorResponse errorResponse = (ErrorResponse) response.getEntity();
assertThat(response.getStatus(), equalTo(INTERNAL_SERVER_ERROR.getStatusCode()));
assertThat(errorResponse.getErrors().size(), equalTo(1));
assertThat(errorResponse.getErrors().get(0), equalTo(INTERNAL_EXCEPTION_MESSAGE));
}
finally
{
LoggingUtils.setLogLevel(previousLogLevel);
}
}
@Test(expected = NullPointerException.class)
public void testGet_nullIdInvalid()
{
resource.get(null);
}
@Test(expected = IllegalArgumentException.class)
public void testGet_emptyIdInvalid()
{
resource.get("");
}
@Test
public void testGet() throws IOException, QueryException, RollUpException
{
resource = new RollUpResource(queryParser, mockStore);
String json = Resources.toString(Resources.getResource("rolluptasks.json"), Charsets.UTF_8);
List<RollupTask> tasks = queryParser.parseRollupTasks(json);
when(mockStore.read()).thenReturn(tasks);
Response response = resource.get(tasks.get(1).getId());
RollupTask responseTask = queryParser.parseRollupTask((String) response.getEntity());
assertThat(response.getStatus(), equalTo(OK.getStatusCode()));
assertThat(responseTask, equalTo(tasks.get(1)));
}
@Test
public void testGet_taskDoesNotExist() throws IOException, QueryException, RollUpException
{
resource = new RollUpResource(queryParser, mockStore);
String json = Resources.toString(Resources.getResource("rolluptasks.json"), Charsets.UTF_8);
List<RollupTask> tasks = queryParser.parseRollupTasks(json);
when(mockStore.read()).thenReturn(tasks);
Response response = resource.get("bogus");
ErrorResponse errorResponse = (ErrorResponse) response.getEntity();
assertThat(response.getStatus(), equalTo(NOT_FOUND.getStatusCode()));
assertThat(errorResponse.getErrors().get(0), equalTo("Resource not found for id bogus"));
}
@Test
public void testGet_internalError() throws IOException, QueryException, RollUpException
{
Level previousLogLevel = LoggingUtils.setLogLevel(Level.OFF);
try
{
when(mockStore.read()).thenThrow(createRollupException());
Response response = resource.get("1");
ErrorResponse errorResponse = (ErrorResponse) response.getEntity();
assertThat(response.getStatus(), equalTo(INTERNAL_SERVER_ERROR.getStatusCode()));
assertThat(errorResponse.getErrors().size(), equalTo(1));
assertThat(errorResponse.getErrors().get(0), equalTo(INTERNAL_EXCEPTION_MESSAGE));
}
finally
{
LoggingUtils.setLogLevel(previousLogLevel);
}
}
@Test(expected = NullPointerException.class)
public void testDelete_nullIdInvalid()
{
resource.delete(null);
}
@Test(expected = IllegalArgumentException.class)
public void testDelete_emptyIdInvalid()
{
resource.delete("");
}
@Test
public void testDelete() throws IOException, QueryException, RollUpException
{
String json = Resources.toString(Resources.getResource("rolluptasks.json"), Charsets.UTF_8);
List<RollupTask> tasks = queryParser.parseRollupTasks(json);
when(mockStore.read()).thenReturn(tasks);
resource = new RollUpResource(queryParser, mockStore);
Response response = resource.delete(tasks.get(0).getId());
assertThat(response.getStatus(), equalTo(NO_CONTENT.getStatusCode()));
assertThat((String) response.getEntity(), equalTo(""));
}
@Test
public void testDelete_internalError() throws IOException, QueryException, RollUpException
{
Level previousLogLevel = LoggingUtils.setLogLevel(Level.OFF);
try
{
String json = Resources.toString(Resources.getResource("rolluptasks.json"), Charsets.UTF_8);
List<RollupTask> tasks = queryParser.parseRollupTasks(json);
when(mockStore.read()).thenReturn(tasks);
doThrow(createRollupException()).when(mockStore).remove(anyString());
Response response = resource.delete(tasks.get(0).getId());
ErrorResponse errorResponse = (ErrorResponse) response.getEntity();
assertThat(response.getStatus(), equalTo(INTERNAL_SERVER_ERROR.getStatusCode()));
assertThat(errorResponse.getErrors().size(), equalTo(1));
assertThat(errorResponse.getErrors().get(0), equalTo(INTERNAL_EXCEPTION_MESSAGE));
}
finally
{
LoggingUtils.setLogLevel(previousLogLevel);
}
}
@Test
public void testDelete_resourceNotExists() throws IOException, QueryException, RollUpException
{
when(mockStore.read()).thenReturn(Collections.<RollupTask>emptyList());
Response response = resource.delete("1");
ErrorResponse errorResponse = (ErrorResponse) response.getEntity();
assertThat(response.getStatus(), equalTo(NOT_FOUND.getStatusCode()));
assertThat(errorResponse.getErrors().size(), equalTo(1));
assertThat(errorResponse.getErrors().get(0), equalTo("Resource not found for id 1"));
}
@Test(expected = NullPointerException.class)
public void testUpdate_nullIdInvalid()
{
resource.update(null, "json");
}
@Test(expected = IllegalArgumentException.class)
public void testUpdate_emptyIdInvalid()
{
resource.update("", "json");
}
@Test(expected = NullPointerException.class)
public void testUpdate_nullJsonInvalid()
{
resource.update("id", null);
}
@Test(expected = IllegalArgumentException.class)
public void testUpdate_emptyJsonInvalid()
{
resource.update("id", "");
}
@Test
public void testUpdate() throws IOException, QueryException, RollUpException
{
resource = new RollUpResource(queryParser, mockStore);
String json = Resources.toString(Resources.getResource("rolluptasks.json"), Charsets.UTF_8);
List<RollupTask> tasks = queryParser.parseRollupTasks(json);
when(mockStore.read()).thenReturn(tasks);
// Replace task 1 with task 2
Response response = resource.update(tasks.get(0).getId(), tasks.get(1).getJson());
@SuppressWarnings("unchecked")
Class<ArrayList<RollupTask>> listClass = (Class<ArrayList<RollupTask>>) (Class) ArrayList.class;
ArgumentCaptor<ArrayList<RollupTask>> captor = ArgumentCaptor.forClass(listClass);
verify(mockStore, times(1)).write(captor.capture());
List<RollupTask> modifiedTasks = captor.getValue();
assertThat(response.getStatus(), equalTo(OK.getStatusCode()));
assertThat(modifiedTasks.size(), equalTo(1));
RollupTask modifiedTask = modifiedTasks.get(0);
assertThat(modifiedTask.getId(), equalTo(tasks.get(0).getId()));
assertThat(modifiedTask.getName(), equalTo(tasks.get(1).getName()));
assertThat(modifiedTask.getJson(), equalTo(tasks.get(1).getJson()));
}
@Test
@SuppressWarnings("unchecked")
public void testUpdate_internalError() throws IOException, QueryException, RollUpException
{
Level previousLogLevel = LoggingUtils.setLogLevel(Level.OFF);
try
{
resource = new RollUpResource(queryParser, mockStore);
String json = Resources.toString(Resources.getResource("rolluptasks.json"), Charsets.UTF_8);
List<RollupTask> tasks = queryParser.parseRollupTasks(json);
when(mockStore.read()).thenReturn(tasks);
//noinspection unchecked
doThrow(createRollupException()).when(mockStore).write((List<RollupTask>) anyCollection());
Response response = resource.update(tasks.get(0).getId(), tasks.get(0).getJson());
ErrorResponse errorResponse = (ErrorResponse) response.getEntity();
assertThat(response.getStatus(), equalTo(INTERNAL_SERVER_ERROR.getStatusCode()));
assertThat(errorResponse.getErrors().size(), equalTo(1));
assertThat(errorResponse.getErrors().get(0), equalTo(INTERNAL_EXCEPTION_MESSAGE));
}
finally{
LoggingUtils.setLogLevel(previousLogLevel);
}
}
@Test
public void testUpdate_resourceNotExists() throws IOException, QueryException, RollUpException
{
when(mockStore.read()).thenReturn(Collections.<RollupTask>emptyList());
Response response = resource.update("1", "json");
ErrorResponse errorResponse = (ErrorResponse) response.getEntity();
assertThat(response.getStatus(), equalTo(NOT_FOUND.getStatusCode()));
assertThat(errorResponse.getErrors().size(), equalTo(1));
assertThat(errorResponse.getErrors().get(0), equalTo("Resource not found for id 1"));
}
private String getBeanValidationMessage()
{
return CONTEXT + " " + BEAN_VALIDATION_ERROR;
}
private BeanValidationException createBeanException() throws BeanValidationException
{
return new BeanValidationException(new QueryParser.SimpleConstraintViolation(CONTEXT, BEAN_VALIDATION_ERROR), "");
}
private Exception createQueryException()
{
return new QueryException(INTERNAL_EXCEPTION_MESSAGE);
}
private Exception createRollupException()
{
return new RollUpException(INTERNAL_EXCEPTION_MESSAGE);
}
private void assertRollupResponse(String expected, RollupTask actual)
{
RollupResponse rollupResponse = new GsonBuilder().create().fromJson(expected, RollupResponse.class);
assertThat(rollupResponse.getId(), not(isEmptyOrNullString()));
assertThat(rollupResponse.getName(), equalTo(actual.getName()));
assertThat(rollupResponse.getAttributes().get("url"), equalTo(RollUpResource.RESOURCE_URL + rollupResponse.getId()));
}
}