package org.ovirt.engine.api.restapi.resource;
import java.util.ArrayList;
import java.util.List;
import java.lang.reflect.Method;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.ovirt.engine.api.model.BaseResource;
import org.ovirt.engine.api.model.Fault;
import org.ovirt.engine.core.common.action.VdcActionParametersBase;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.businessentities.AsyncTaskStatus;
import org.ovirt.engine.core.common.businessentities.VDSGroup;
import org.ovirt.engine.core.common.interfaces.SearchType;
import org.ovirt.engine.core.common.queries.GetTasksStatusesByTasksIDsParameters;
import org.ovirt.engine.core.common.queries.SearchParameters;
import org.ovirt.engine.core.common.queries.VdcQueryParametersBase;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.compat.Guid;
import org.junit.Test;
import static org.ovirt.engine.api.restapi.test.util.TestHelper.eqActionParams;
import static org.ovirt.engine.api.restapi.test.util.TestHelper.eqQueryParams;
import static org.ovirt.engine.api.restapi.test.util.TestHelper.eqSearchParams;
import static org.easymock.classextension.EasyMock.eq;
import static org.easymock.classextension.EasyMock.expect;
public abstract class AbstractBackendCollectionResourceTest<R extends BaseResource, Q /* extends IVdcQueryable */, C extends AbstractBackendCollectionResource<R, Q>>
extends AbstractBackendResourceTest<R, Q> {
protected static final String QUERY = "name=s* AND id=*0";
protected C collection;
protected SearchType searchType;
protected String prefix;
protected AbstractBackendCollectionResourceTest(C collection, SearchType searchType,
String prefix) {
this.collection = collection;
this.searchType = searchType;
this.prefix = prefix;
}
protected abstract List<R> getCollection();
protected void init() {
initResource(collection);
}
@Test
public void testList() throws Exception {
UriInfo uriInfo = setUpUriExpectations(null);
setUpQueryExpectations("");
collection.setUriInfo(uriInfo);
verifyCollection(getCollection());
}
@Test
public void testQuery() throws Exception {
UriInfo uriInfo = setUpUriExpectations(QUERY);
setUpQueryExpectations(QUERY);
collection.setUriInfo(uriInfo);
verifyCollection(getCollection());
}
@Test
public void testListFailure() throws Exception {
UriInfo uriInfo = setUpUriExpectations(null);
setUpQueryExpectations("", FAILURE);
collection.setUriInfo(uriInfo);
try {
getCollection();
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
assertTrue(wae.getResponse().getEntity() instanceof Fault);
assertEquals(mockl10n(FAILURE), ((Fault) wae.getResponse().getEntity()).getDetail());
}
}
@Test
public void testListCrash() throws Exception {
UriInfo uriInfo = setUpUriExpectations(null);
Throwable t = new RuntimeException(FAILURE);
setUpQueryExpectations("", t);
collection.setUriInfo(uriInfo);
try {
getCollection();
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyFault(wae, BACKEND_FAILED_SERVER_LOCALE, t);
}
}
@Test
public void testListCrashClientLocale() throws Exception {
UriInfo uriInfo = setUpUriExpectations(null);
locales.add(CLIENT_LOCALE);
Throwable t = new RuntimeException(FAILURE);
setUpQueryExpectations("", t);
collection.setUriInfo(uriInfo);
try {
getCollection();
fail("expected WebApplicationException");
} catch (WebApplicationException wae) {
verifyFault(wae, BACKEND_FAILED_CLIENT_LOCALE, t);
} finally {
locales.clear();
}
}
@SuppressWarnings("unchecked")
@Test
public void testSubResourceInjection() throws Exception {
control.replay();
// walk super-interface hierarchy to find non-inherited method annotations
for (Class<?> resourceInterface : collection.getClass().getInterfaces()) {
for (Method method : resourceInterface.getDeclaredMethods()) {
if (method.isAnnotationPresent(Path.class) && isSubResourceLocator(method)) {
Object rawSubResource = method.invoke(collection, getSubResourceId());
if (rawSubResource instanceof AbstractBackendResource) {
AbstractBackendResource<R, Q> subResource = (AbstractBackendResource<R, Q>)rawSubResource;
assertNotNull(subResource.getBackend());
assertNotNull(subResource.getSessionHelper());
assertNotNull(subResource.getMappingLocator());
}
}
}
}
}
protected String getSubResourceId() {
return GUIDS[3].toString();
}
protected boolean isSubResourceLocator(Method method) {
return method.getName().startsWith("get")
&& method.getName().toLowerCase().endsWith("resource")
&& method.getParameterTypes().length == 1
&& String.class.equals(method.getParameterTypes()[0])
&& method.getReturnType() != null;
}
protected void setUriInfo(UriInfo uriInfo) {
collection.setUriInfo(uriInfo);
}
@SuppressWarnings("unchecked")
protected UriInfo setUpUriExpectations(String query) {
UriInfo uriInfo = setUpBasicUriExpectations();
MultivaluedMap<String, String> queries = control.createMock(MultivaluedMap.class);
List<String> queryParam = new ArrayList<String>();
if (!(query == null || "".equals(query))) {
queryParam.add(QUERY);
}
expect(queries.get("search")).andReturn(queryParam).anyTimes();
expect(uriInfo.getQueryParameters()).andReturn(queries).anyTimes();
return uriInfo;
}
protected void setUpQueryExpectations(String query) throws Exception {
setUpQueryExpectations(query, null);
}
protected void setUpQueryExpectations(String query, Object failure) throws Exception {
VdcQueryReturnValue queryResult = control.createMock(VdcQueryReturnValue.class);
SearchParameters params = new SearchParameters(prefix + query, searchType);
expect(queryResult.getSucceeded()).andReturn(failure == null).anyTimes();
if (failure == null) {
List<Q> entities = new ArrayList<Q>();
for (int i = 0; i < NAMES.length; i++) {
entities.add(getEntity(i));
}
expect(queryResult.getReturnValue()).andReturn(entities).anyTimes();
} else {
if (failure instanceof String) {
expect(queryResult.getExceptionString()).andReturn((String) failure).anyTimes();
setUpL10nExpectations((String)failure);
} else if (failure instanceof Exception) {
expect(queryResult.getExceptionString()).andThrow((Exception) failure).anyTimes();
}
}
expect(backend.RunQuery(eq(VdcQueryType.Search), eqSearchParams(params))).andReturn(
queryResult);
control.replay();
}
protected void setUpCreationExpectations(VdcActionType task,
Class<? extends VdcActionParametersBase> taskClass,
String[] taskNames,
Object[] taskValues,
boolean canDo,
boolean success,
Object taskReturn,
VdcQueryType query,
Class<? extends VdcQueryParametersBase> queryClass,
String[] queryNames,
Object[] queryValues,
Object queryReturn) {
setUpCreationExpectations(task,
taskClass,
taskNames,
taskValues,
canDo,
success,
taskReturn,
null,
null,
query,
queryClass,
queryNames,
queryValues,
queryReturn);
}
protected void setUpCreationExpectations(VdcActionType task,
Class<? extends VdcActionParametersBase> taskClass,
String[] taskNames,
Object[] taskValues,
boolean canDo,
boolean success,
Object taskReturn,
ArrayList<Guid> asyncTasks,
ArrayList<AsyncTaskStatus> asyncStatuses,
VdcQueryType query,
Class<? extends VdcQueryParametersBase> queryClass,
String[] queryNames,
Object[] queryValues,
Object queryReturn) {
VdcReturnValueBase taskResult = control.createMock(VdcReturnValueBase.class);
expect(taskResult.getCanDoAction()).andReturn(canDo).anyTimes();
if (canDo) {
expect(taskResult.getSucceeded()).andReturn(success).anyTimes();
if (success) {
expect(taskResult.getActionReturnValue()).andReturn(taskReturn).anyTimes();
} else {
expect(taskResult.getExecuteFailedMessages()).andReturn(asList(FAILURE)).anyTimes();
}
} else {
expect(taskResult.getCanDoActionMessages()).andReturn(asList(CANT_DO)).anyTimes();
}
expect(taskResult.getHasAsyncTasks()).andReturn(asyncTasks != null).anyTimes();
if (asyncTasks != null) {
expect(taskResult.getTaskIdList()).andReturn(asyncTasks).anyTimes();
VdcQueryReturnValue monitorResult = control.createMock(VdcQueryReturnValue.class);
expect(monitorResult.getSucceeded()).andReturn(success).anyTimes();
expect(monitorResult.getReturnValue()).andReturn(asyncStatuses).anyTimes();
expect(backend.RunQuery(eq(VdcQueryType.GetTasksStatusesByTasksIDs),
eqQueryParams(GetTasksStatusesByTasksIDsParameters.class,
addSession(new String[]{}),
addSession(new Object[]{})))).andReturn(monitorResult);
}
expect(backend.RunAction(eq(task), eqActionParams(taskClass, addSession(taskNames), addSession(taskValues))))
.andReturn(taskResult);
if (canDo && success && query != null) {
setUpEntityQueryExpectations(query, queryClass, queryNames, queryValues, queryReturn);
}
control.replay();
}
protected void setUpHttpHeaderExpectations(String name, String value) {
expect(httpHeaders.getRequestHeader(eq(name))).andReturn(asList(value));
}
protected VDSGroup setUpVDSGroup(Guid id) {
VDSGroup cluster = control.createMock(VDSGroup.class);
expect(cluster.getID()).andReturn(id).anyTimes();
return cluster;
}
protected void verifyCollection(List<R> collection) throws Exception {
assertNotNull(collection);
assertEquals(NAMES.length, collection.size());
for (int i = 0; i < NAMES.length; i++) {
verifyModel(collection.get(i), i);
}
}
protected void verifyRemove(Response response) {
assertNotNull(response);
assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
}
}