package org.camunda.bpm.engine.rest;

import static com.jayway.restassured.RestAssured.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.core.Response.Status;

import org.camunda.bpm.engine.MismatchingMessageCorrelationException;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.rest.helper.EqualsMap;
import org.junit.Before;
import org.junit.Test;

public abstract class AbstractMessageRestServiceTest extends AbstractRestServiceTest {

  protected static final String MESSAGE_URL = TEST_RESOURCE_ROOT_PATH + "/message";
  
  private RuntimeService runtimeServiceMock;
  
  @Before
  public void setupMocks() {
    runtimeServiceMock = mock(RuntimeService.class);
    when(processEngine.getRuntimeService()).thenReturn(runtimeServiceMock);
  }
  
  @Test
  public void testFullMessageCorrelation() {
    String messageName = "aMessageName";
    String businessKey = "aBusinessKey";
    Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("aKey", "aValue");
    
    Map<String, Object> correlationKeys = new HashMap<String, Object>();
    correlationKeys.put("aKey", "aValue");
    correlationKeys.put("anotherKey", 1);
    correlationKeys.put("aThirdKey", true);
    
    Map<String, Object> messageParameters = new HashMap<String, Object>();
    messageParameters.put("messageName", messageName);
    messageParameters.put("correlationKeys", correlationKeys);
    messageParameters.put("processVariables", variables);
    messageParameters.put("businessKey", businessKey);
    
    given().contentType(POST_JSON_CONTENT_TYPE).body(messageParameters)
      .then().expect().statusCode(Status.NO_CONTENT.getStatusCode())
      .when().post(MESSAGE_URL);
    
    verify(runtimeServiceMock).correlateMessage(eq(messageName), eq(businessKey), 
        argThat(new EqualsMap(correlationKeys)), argThat(new EqualsMap(variables)));
  }
  
  @Test
  public void testMessageNameOnlyCorrelation() {
    String messageName = "aMessageName";
    
    Map<String, Object> messageParameters = new HashMap<String, Object>();
    messageParameters.put("messageName", messageName);
    
    given().contentType(POST_JSON_CONTENT_TYPE).body(messageParameters)
      .then().expect().statusCode(Status.NO_CONTENT.getStatusCode())
      .when().post(MESSAGE_URL);
    
    verify(runtimeServiceMock).correlateMessage(eq(messageName), eq((String) null), 
        argThat(new EqualsMap(null)), argThat(new EqualsMap(null)));
  }
  
  @Test
  public void testMismatchingCorrelation() {
    String messageName = "aMessage";
    
    doThrow(new MismatchingMessageCorrelationException(messageName, "Expected exception: cannot correlate"))
      .when(runtimeServiceMock).correlateMessage(any(String.class), any(String.class), any(Map.class), any(Map.class));
    
    Map<String, Object> messageParameters = new HashMap<String, Object>();
    messageParameters.put("messageName", messageName);
    given().contentType(POST_JSON_CONTENT_TYPE).body(messageParameters)
      .then().expect().statusCode(Status.BAD_REQUEST.getStatusCode())
      .when().post(MESSAGE_URL);
  }
  
  @Test
  public void testNoMessageNameCorrelation() {
    given().contentType(POST_JSON_CONTENT_TYPE).body(EMPTY_JSON_OBJECT)
      .then().expect().statusCode(Status.BAD_REQUEST.getStatusCode())
      .when().post(MESSAGE_URL);
  }
}

@@ -537,16 +537,70 @@
 eption;%0A
+import org.camunda.bpm.engine.ProcessEngineException;%0A
 import o
@@ -3472,32 +3472,714 @@
 %0A  %7D%0A  %0A  @Test%0A
+  public void testFailingInstantiation() %7B%0A    String messageName = %22aMessage%22;%0A    %0A    // thrown, if instantiation of the process or signalling the instance fails%0A    doThrow(new ProcessEngineException(%22Expected exception%22))%0A      .when(runtimeServiceMock).correlateMessage(any(String.class), any(String.class), any(Map.class), any(Map.class));%0A    %0A    Map%3CString, Object%3E messageParameters = new HashMap%3CString, Object%3E();%0A    messageParameters.put(%22messageName%22, messageName);%0A    given().contentType(POST_JSON_CONTENT_TYPE).body(messageParameters)%0A      .then().expect().statusCode(Status.INTERNAL_SERVER_ERROR.getStatusCode())%0A      .when().post(MESSAGE_URL);%0A  %7D%0A  %0A  @Test%0A
   public void te

add test case for POST /message