package org.camunda.bpm.engine.rest;
import static com.jayway.restassured.RestAssured.expect;
import static com.jayway.restassured.RestAssured.given;
import static com.jayway.restassured.path.json.JsonPath.from;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ws.rs.core.Response.Status;
import javax.xml.registry.InvalidRequestException;
import org.camunda.bpm.engine.rest.helper.MockProvider;
import org.camunda.bpm.engine.runtime.Execution;
import org.camunda.bpm.engine.runtime.ExecutionQuery;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mockito;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.response.Response;
public abstract class AbstractExecutionRestServiceQueryTest extends
AbstractRestServiceTest {
protected static final String EXECUTION_QUERY_URL = TEST_RESOURCE_ROOT_PATH + "/execution";
protected static final String EXECUTION_COUNT_QUERY_URL = EXECUTION_QUERY_URL + "/count";
private ExecutionQuery mockedQuery;
@Before
public void setUpRuntimeData() {
mockedQuery = setUpMockExecutionQuery(createMockExecutionList());
}
private ExecutionQuery setUpMockExecutionQuery(List<Execution> mockedExecutions) {
ExecutionQuery sampleExecutionQuery = mock(ExecutionQuery.class);
when(sampleExecutionQuery.list()).thenReturn(mockedExecutions);
when(sampleExecutionQuery.count()).thenReturn((long) mockedExecutions.size());
when(processEngine.getRuntimeService().createExecutionQuery()).thenReturn(sampleExecutionQuery);
return sampleExecutionQuery;
}
private List<Execution> createMockExecutionList() {
List<Execution> mocks = new ArrayList<Execution>();
mocks.add(MockProvider.createMockExecution());
return mocks;
}
@Test
public void testInvalidVariableRequests() {
// invalid comparator
String invalidComparator = "anInvalidComparator";
String variableName = "varName";
String variableValue = "varValue";
String queryValue = variableName + "_" + invalidComparator + "_" + variableValue;
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.BAD_REQUEST.getStatusCode()).contentType(ContentType.JSON)
.body("type", equalTo(InvalidRequestException.class.getSimpleName()))
.body("message", containsString("Invalid variable comparator specified: " + invalidComparator))
.when().get(EXECUTION_QUERY_URL);
given().queryParam("processVariables", queryValue)
.then().expect().statusCode(Status.BAD_REQUEST.getStatusCode()).contentType(ContentType.JSON)
.body("type", equalTo(InvalidRequestException.class.getSimpleName()))
.body("message", containsString("Invalid process variable comparator specified: " + invalidComparator))
.when().get(EXECUTION_QUERY_URL);
// invalid format
queryValue = "invalidFormattedVariableQuery";
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.BAD_REQUEST.getStatusCode()).contentType(ContentType.JSON)
.body("type", equalTo(InvalidRequestException.class.getSimpleName()))
.body("message", containsString("variable query parameter has to have format KEY_OPERATOR_VALUE"))
.when().get(EXECUTION_QUERY_URL);
given().queryParam("processVariables", queryValue)
.then().expect().statusCode(Status.BAD_REQUEST.getStatusCode()).contentType(ContentType.JSON)
.body("type", equalTo(InvalidRequestException.class.getSimpleName()))
.body("message", containsString("variable query parameter has to have format KEY_OPERATOR_VALUE"))
.when().get(EXECUTION_QUERY_URL);
}
@Test
public void testInvalidSortingOptions() {
executeAndVerifySorting("anInvalidSortByOption", "asc", Status.BAD_REQUEST);
executeAndVerifySorting("definitionId", "anInvalidSortOrderOption", Status.BAD_REQUEST);
}
protected void executeAndVerifySorting(String sortBy, String sortOrder, Status expectedStatus) {
given().queryParam("sortBy", sortBy).queryParam("sortOrder", sortOrder)
.then().expect().statusCode(expectedStatus.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
}
@Test
public void testSortByParameterOnly() {
given().queryParam("sortBy", "definitionId")
.then().expect().statusCode(Status.BAD_REQUEST.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
}
@Test
public void testSortOrderParameterOnly() {
given().queryParam("sortOrder", "asc")
.then().expect().statusCode(Status.BAD_REQUEST.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
}
@Test
public void testExecutionRetrieval() {
String queryKey = "key";
Response response = given().queryParam("processDefinitionKey", queryKey)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
// assert query invocation
InOrder inOrder = Mockito.inOrder(mockedQuery);
inOrder.verify(mockedQuery).processDefinitionKey(queryKey);
inOrder.verify(mockedQuery).list();
String content = response.asString();
List<String> executions = from(content).getList("");
Assert.assertEquals("There should be one execution returned.", 1, executions.size());
Assert.assertNotNull("There should be one execution returned", executions.get(0));
String returnedExecutionId = from(content).getString("[0].id");
Boolean returnedIsEnded = from(content).getBoolean("[0].ended");
String returnedProcessInstanceId = from(content).getString("[0].processInstanceId");
Assert.assertEquals(MockProvider.EXAMPLE_EXECUTION_ID, returnedExecutionId);
Assert.assertEquals(MockProvider.EXAMPLE_EXECUTION_IS_ENDED, returnedIsEnded);
Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_ID, returnedProcessInstanceId);
}
@Test
public void testIncompleteExecution() {
setUpMockExecutionQuery(createIncompleteMockExecutions());
Response response = expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
String content = response.asString();
String returnedProcessInstanceId = from(content).getString("[0].processInstanceId");
Assert.assertNull("Should be null, as it is also null in the original execution on the server.",
returnedProcessInstanceId);
}
private List<Execution> createIncompleteMockExecutions() {
List<Execution> mocks = new ArrayList<Execution>();
Execution mockExecution = mock(Execution.class);
when(mockExecution.getId()).thenReturn(MockProvider.EXAMPLE_EXECUTION_ID);
mocks.add(mockExecution);
return mocks;
}
@Test
public void testNoParametersQuery() {
expect().statusCode(Status.OK.getStatusCode()).when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).list();
verifyNoMoreInteractions(mockedQuery);
}
@Test
public void testAdditionalParametersExcludingVariables() {
Map<String, String> queryParameters = getCompleteQueryParameters();
given().queryParams(queryParameters)
.expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).processInstanceBusinessKey(queryParameters.get("businessKey"));
verify(mockedQuery).processInstanceId(queryParameters.get("processInstanceId"));
verify(mockedQuery).processDefinitionKey(queryParameters.get("processDefinitionKey"));
verify(mockedQuery).processDefinitionId(queryParameters.get("processDefinitionId"));
verify(mockedQuery).activityId(queryParameters.get("activityId"));
verify(mockedQuery).signalEventSubscriptionName(queryParameters.get("signalEventSubscriptionName"));
verify(mockedQuery).messageEventSubscriptionName(queryParameters.get("messageEventSubscriptionName"));
verify(mockedQuery).active();
verify(mockedQuery).suspended();
verify(mockedQuery).incidentId(queryParameters.get("incidentId"));
verify(mockedQuery).incidentMessage(queryParameters.get("incidentMessage"));
verify(mockedQuery).incidentMessageLike(queryParameters.get("incidentMessageLike"));
verify(mockedQuery).incidentType(queryParameters.get("incidentType"));
verify(mockedQuery).list();
}
private Map<String, String> getCompleteQueryParameters() {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("businessKey", "aBusinessKey");
parameters.put("processInstanceId", "aProcInstId");
parameters.put("processDefinitionKey", "aProcDefKey");
parameters.put("processDefinitionId", "aProcDefId");
parameters.put("activityId", "anActivityId");
parameters.put("signalEventSubscriptionName", "anEventName");
parameters.put("messageEventSubscriptionName", "aMessageName");
parameters.put("suspended", "true");
parameters.put("active", "true");
parameters.put("incidentId", "incId");
parameters.put("incidentType", "incType");
parameters.put("incidentMessage", "incMessage");
parameters.put("incidentMessageLike", "incMessageLike");
return parameters;
}
@Test
public void testVariableParameters() {
String variableName = "varName";
String variableValue = "varValue";
String queryValue = variableName + "_eq_" + variableValue;
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).variableValueEquals(variableName, variableValue);
queryValue = variableName + "_gt_" + variableValue;
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).variableValueGreaterThan(variableName, variableValue);
queryValue = variableName + "_gteq_" + variableValue;
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).variableValueGreaterThanOrEqual(variableName, variableValue);
queryValue = variableName + "_lt_" + variableValue;
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).variableValueLessThan(variableName, variableValue);
queryValue = variableName + "_lteq_" + variableValue;
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).variableValueLessThanOrEqual(variableName, variableValue);
queryValue = variableName + "_like_" + variableValue;
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).variableValueLike(variableName, variableValue);
queryValue = variableName + "_neq_" + variableValue;
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).variableValueNotEquals(variableName, variableValue);
}
@Test
public void testProcessVariableParameters() {
String variableName = "varName";
String variableValue = "varValue";
String queryValue = variableName + "_eq_" + variableValue;
given().queryParam("processVariables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).processVariableValueEquals(variableName, variableValue);
queryValue = variableName + "_neq_" + variableValue;
given().queryParam("processVariables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).processVariableValueNotEquals(variableName, variableValue);
}
@Test
public void testMultipleVariableParameters() {
String variableName1 = "varName";
String variableValue1 = "varValue";
String variableParameter1 = variableName1 + "_eq_" + variableValue1;
String variableName2 = "anotherVarName";
String variableValue2 = "anotherVarValue";
String variableParameter2 = variableName2 + "_neq_" + variableValue2;
String queryValue = variableParameter1 + "," + variableParameter2;
given().queryParam("variables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).variableValueEquals(variableName1, variableValue1);
verify(mockedQuery).variableValueNotEquals(variableName2, variableValue2);
}
@Test
public void testMultipleProcessVariableParameters() {
String variableName1 = "varName";
String variableValue1 = "varValue";
String variableParameter1 = variableName1 + "_eq_" + variableValue1;
String variableName2 = "anotherVarName";
String variableValue2 = "anotherVarValue";
String variableParameter2 = variableName2 + "_neq_" + variableValue2;
String queryValue = variableParameter1 + "," + variableParameter2;
given().queryParam("processVariables", queryValue)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).processVariableValueEquals(variableName1, variableValue1);
verify(mockedQuery).processVariableValueNotEquals(variableName2, variableValue2);
}
@Test
public void testMultipleVariableParametersAsPost() {
String variableName = "varName";
String variableValue = "varValue";
String anotherVariableName = "anotherVarName";
Integer anotherVariableValue = 30;
Map<String, Object> variableJson = new HashMap<String, Object>();
variableJson.put("name", variableName);
variableJson.put("operator", "eq");
variableJson.put("value", variableValue);
Map<String, Object> anotherVariableJson = new HashMap<String, Object>();
anotherVariableJson.put("name", anotherVariableName);
anotherVariableJson.put("operator", "neq");
anotherVariableJson.put("value", anotherVariableValue);
List<Map<String, Object>> variables = new ArrayList<Map<String, Object>>();
variables.add(variableJson);
variables.add(anotherVariableJson);
Map<String, Object> json = new HashMap<String, Object>();
json.put("variables", variables);
given().contentType(POST_JSON_CONTENT_TYPE).body(json)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().post(EXECUTION_QUERY_URL);
verify(mockedQuery).variableValueEquals(variableName, variableValue);
verify(mockedQuery).variableValueNotEquals(anotherVariableName, anotherVariableValue);
}
@Test
public void testMultipleProcessVariableParametersAsPost() {
String variableName = "varName";
String variableValue = "varValue";
String anotherVariableName = "anotherVarName";
Integer anotherVariableValue = 30;
Map<String, Object> variableJson = new HashMap<String, Object>();
variableJson.put("name", variableName);
variableJson.put("operator", "eq");
variableJson.put("value", variableValue);
Map<String, Object> anotherVariableJson = new HashMap<String, Object>();
anotherVariableJson.put("name", anotherVariableName);
anotherVariableJson.put("operator", "neq");
anotherVariableJson.put("value", anotherVariableValue);
List<Map<String, Object>> variables = new ArrayList<Map<String, Object>>();
variables.add(variableJson);
variables.add(anotherVariableJson);
Map<String, Object> json = new HashMap<String, Object>();
json.put("processVariables", variables);
given().contentType(POST_JSON_CONTENT_TYPE).body(json)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().post(EXECUTION_QUERY_URL);
verify(mockedQuery).processVariableValueEquals(variableName, variableValue);
verify(mockedQuery).processVariableValueNotEquals(anotherVariableName, anotherVariableValue);
}
@Test
public void testCompletePostParameters() {
Map<String, String> queryParameters = getCompleteQueryParameters();
given().contentType(POST_JSON_CONTENT_TYPE).body(queryParameters)
.expect().statusCode(Status.OK.getStatusCode())
.when().post(EXECUTION_QUERY_URL);
verify(mockedQuery).processInstanceBusinessKey(queryParameters.get("businessKey"));
verify(mockedQuery).processInstanceId(queryParameters.get("processInstanceId"));
verify(mockedQuery).processDefinitionKey(queryParameters.get("processDefinitionKey"));
verify(mockedQuery).processDefinitionId(queryParameters.get("processDefinitionId"));
verify(mockedQuery).activityId(queryParameters.get("activityId"));
verify(mockedQuery).signalEventSubscriptionName(queryParameters.get("signalEventSubscriptionName"));
verify(mockedQuery).messageEventSubscriptionName(queryParameters.get("messageEventSubscriptionName"));
verify(mockedQuery).active();
verify(mockedQuery).suspended();
verify(mockedQuery).incidentId(queryParameters.get("incidentId"));
verify(mockedQuery).incidentMessage(queryParameters.get("incidentMessage"));
verify(mockedQuery).incidentMessageLike(queryParameters.get("incidentMessageLike"));
verify(mockedQuery).incidentType(queryParameters.get("incidentType"));
verify(mockedQuery).list();
}
@Test
public void testSortingParameters() {
InOrder inOrder = Mockito.inOrder(mockedQuery);
executeAndVerifySorting("instanceId", "asc", Status.OK);
inOrder.verify(mockedQuery).orderByProcessInstanceId();
inOrder.verify(mockedQuery).asc();
inOrder = Mockito.inOrder(mockedQuery);
executeAndVerifySorting("definitionKey", "desc", Status.OK);
inOrder.verify(mockedQuery).orderByProcessDefinitionKey();
inOrder.verify(mockedQuery).desc();
inOrder = Mockito.inOrder(mockedQuery);
executeAndVerifySorting("definitionId", "asc", Status.OK);
inOrder.verify(mockedQuery).orderByProcessDefinitionId();
inOrder.verify(mockedQuery).asc();
}
@Test
public void testSuccessfulPagination() {
int firstResult = 0;
int maxResults = 10;
given().queryParam("firstResult", firstResult).queryParam("maxResults", maxResults)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).listPage(firstResult, maxResults);
}
/**
* If parameter "firstResult" is missing, we expect 0 as default.
*/
@Test
public void testMissingFirstResultParameter() {
int maxResults = 10;
given().queryParam("maxResults", maxResults)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).listPage(0, maxResults);
}
/**
* If parameter "maxResults" is missing, we expect Integer.MAX_VALUE as default.
*/
@Test
public void testMissingMaxResultsParameter() {
int firstResult = 10;
given().queryParam("firstResult", firstResult)
.then().expect().statusCode(Status.OK.getStatusCode())
.when().get(EXECUTION_QUERY_URL);
verify(mockedQuery).listPage(firstResult, Integer.MAX_VALUE);
}
@Test
public void testQueryCount() {
expect().statusCode(Status.OK.getStatusCode())
.body("count", equalTo(1))
.when().get(EXECUTION_COUNT_QUERY_URL);
verify(mockedQuery).count();
}
@Test
public void testQueryCountForPost() {
given().contentType(POST_JSON_CONTENT_TYPE).body(EMPTY_JSON_OBJECT)
.expect().statusCode(Status.OK.getStatusCode())
.body("count", equalTo(1))
.when().post(EXECUTION_COUNT_QUERY_URL);
verify(mockedQuery).count();
}
}