/*
* Copyright 2016 JBoss by Red Hat.
*
* 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 org.kie.server.integrationtests.jbpm;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.junit.After;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runners.Parameterized;
import org.kie.server.api.marshalling.MarshallingFormat;
import org.kie.server.api.model.ReleaseId;
import org.kie.server.api.model.instance.ProcessInstance;
import org.kie.server.api.model.instance.TaskInstance;
import org.kie.server.api.model.instance.TaskSummary;
import org.kie.server.client.KieServicesConfiguration;
import org.kie.server.integrationtests.category.Email;
import org.kie.server.integrationtests.category.Unstable;
import org.kie.server.integrationtests.config.TestConfig;
import org.kie.server.integrationtests.shared.KieServerAssert;
import org.kie.server.integrationtests.shared.KieServerDeployer;
import org.subethamail.wiser.Wiser;
import org.subethamail.wiser.WiserMessage;
@Category(Email.class)
public class UserTaskEscalationIntegrationTest extends JbpmKieServerBaseIntegrationTest {
private static final String ESCALATION_TEXT = "Escalation text";
private static final String FROM_EMAIL = "kie-server-test@domain.com";
private static final String EMAIL_DOMAIN = "@domain.com";
private static final int SMTP_PORT = 2525;
private static final String SMTP_HOST = "localhost";
private static ReleaseId releaseId = new ReleaseId("org.kie.server.testing", "definition-project",
"1.0.0.Final");
private final static Map<String, Object> params = new HashMap<String, Object>();
static {
params.put("actor", USER_YODA);
params.put("reassignTo", USER_JOHN);
params.put("escUser", USER_JOHN);
params.put("escalation", ESCALATION_TEXT);
}
private Wiser wiser;
@Parameterized.Parameters(name = "{index}: {0} {1}")
public static Collection<Object[]> data() {
KieServicesConfiguration configuration = createKieServicesRestConfiguration();
Collection<Object[]> parameterData = new ArrayList<Object[]>(Arrays.asList(new Object[][] {
{MarshallingFormat.JAXB, configuration}
}
));
return parameterData;
}
@Before
public void startWiser() {
wiser = new Wiser();
wiser.setHostname(SMTP_HOST);
wiser.setPort(SMTP_PORT);
wiser.start();
}
@After
public void stopWiser() {
if (wiser != null) {
wiser.stop();
}
}
@BeforeClass
public static void buildAndDeployArtifacts() {
KieServerDeployer.buildAndDeployCommonMavenParent();
KieServerDeployer.buildAndDeployMavenProject(ClassLoader.class.getResource("/kjars-sources/definition-project").getFile());
createContainer(CONTAINER_ID, releaseId);
}
@Test
public void testEscalation() throws InterruptedException, MessagingException, Exception {
Long processInstanceId = processClient.startProcess(CONTAINER_ID, PROCESS_ID_USERTASK_ESCALATION, params);
assertNotNull(processInstanceId);
assertTrue(processInstanceId > 0);
try {
List<TaskSummary> taskList = taskClient.findTasksAssignedAsPotentialOwner(USER_YODA, 0, 10);
assertNotNull(taskList);
assertEquals(1, taskList.size());
TaskSummary taskSummary = taskList.get(0);
assertEquals("User Task", taskSummary.getName());
Long taskId = taskSummary.getId();
TaskInstance taskInstance = taskClient.findTaskById(taskId);
assertNotNull(taskInstance);
assertEquals(USER_YODA, taskInstance.getActualOwner());
changeUser(USER_JOHN);
waitForAssign(taskId, USER_JOHN);
taskList = taskClient.findTasksAssignedAsPotentialOwner(USER_JOHN, 0, 10);
assertNotNull(taskList);
assertEquals(1, taskList.size());
taskId = taskList.get(0).getId();
taskInstance = taskClient.findTaskById(taskId);
assertNotNull(taskInstance);
taskClient.startTask(CONTAINER_ID, taskId, USER_JOHN);
taskInstance = taskClient.findTaskById(taskId);
assertNotNull(taskInstance);
assertEquals(USER_JOHN, taskInstance.getActualOwner());
waitForEmailsRecieve(wiser);
taskClient.completeTask(CONTAINER_ID, taskId, USER_JOHN, new HashMap<String, Object>());
ProcessInstance processInstance = processClient.getProcessInstance(CONTAINER_ID, processInstanceId);
assertNotNull(processInstance);
assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.getState().intValue());
assertEmails("Escalation");
} catch (Exception e) {
processClient.abortProcessInstance(CONTAINER_ID, processInstanceId);
throw e;
} finally {
changeUser(TestConfig.getUsername());
}
}
@Test
@Category(Unstable.class)
public void testCompleteTaskBeforeEscalation() throws InterruptedException {
// Unstable on slow DBs where starting of task is called after escalation timeout.
Long processInstanceId = processClient.startProcess(CONTAINER_ID, PROCESS_ID_USERTASK_ESCALATION, params);
assertNotNull(processInstanceId);
assertTrue(processInstanceId > 0);
List<TaskSummary> taskList = taskClient.findTasksAssignedAsPotentialOwner(USER_YODA, 0, 10);
assertNotNull(taskList);
assertEquals(1, taskList.size());
TaskSummary taskSummary = taskList.get(0);
assertEquals("User Task", taskSummary.getName());
Long taskId = taskSummary.getId();
taskClient.startTask(CONTAINER_ID, taskId, USER_YODA);
taskClient.completeTask(CONTAINER_ID, taskId, USER_YODA, new HashMap<String, Object>());
ProcessInstance processInstance = processClient.getProcessInstance(CONTAINER_ID, processInstanceId);
assertNotNull(processInstance);
assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.getState().intValue());
KieServerAssert.assertNullOrEmpty("Email recieved!", wiser.getMessages());
//wait while, cause email is sent 6s after task start
Thread.sleep(8000l);
KieServerAssert.assertNullOrEmpty("Email recieved!", wiser.getMessages());
}
private void assertEmails(final String subj) throws MessagingException, IOException {
//wiser shoudl catch 2 messages (one for John and one for Administrator)
List<WiserMessage> messages = wiser.getMessages();
assertNotNull(messages);
assertEquals(2, messages.size());
for (WiserMessage message : messages) {
MimeMessage receivedMessage = message.getMimeMessage();
assertNotNull(receivedMessage);
assertEquals(subj, receivedMessage.getSubject());
assertEquals(ESCALATION_TEXT, (String) receivedMessage.getContent());
InternetAddress[] from = (InternetAddress[]) receivedMessage.getFrom();
assertEquals(1, from.length);
assertEquals(FROM_EMAIL, from[0].getAddress());
InternetAddress[] to = (InternetAddress[]) receivedMessage.getAllRecipients();
assertEquals(2, to.length);
if (to[0].getAddress().equals(USER_JOHN + EMAIL_DOMAIN)) {
assertEquals(USER_JOHN + EMAIL_DOMAIN, to[0].getAddress());
assertEquals(USER_ADMINISTRATOR + EMAIL_DOMAIN, to[1].getAddress());
} else {
assertEquals(USER_ADMINISTRATOR + EMAIL_DOMAIN, to[0].getAddress());
assertEquals(USER_JOHN + EMAIL_DOMAIN, to[1].getAddress());
}
}
}
private static final long SERVICE_TIMEOUT = 30000;
private static final long TIMEOUT_BETWEEN_CALLS = 200;
protected void waitForEmailsRecieve(Wiser wiser) throws Exception {
long timeoutTime = Calendar.getInstance().getTimeInMillis() + SERVICE_TIMEOUT;
while (Calendar.getInstance().getTimeInMillis() < timeoutTime) {
if (wiser.getMessages().isEmpty()) {
Thread.sleep(TIMEOUT_BETWEEN_CALLS);
} else {
return;
}
}
throw new TimeoutException("Timeout while waiting for process instance to finish.");
}
protected void waitForAssign(Long taskId, String potencialOwner) throws Exception {
long timeoutTime = Calendar.getInstance().getTimeInMillis() + SERVICE_TIMEOUT;
while (Calendar.getInstance().getTimeInMillis() < timeoutTime) {
if (taskClient.findTasksAssignedAsPotentialOwner(potencialOwner, 0, 10).isEmpty()) {
Thread.sleep(TIMEOUT_BETWEEN_CALLS);
} else {
return;
}
}
throw new TimeoutException("Timeout while waiting for process instance to finish.");
}
}