/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jbpm.test; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.jms.Session; import org.jbpm.api.Configuration; import org.jbpm.api.Execution; import org.jbpm.api.ExecutionService; import org.jbpm.api.HistoryService; import org.jbpm.api.IdentityService; import org.jbpm.api.JbpmException; import org.jbpm.api.ManagementService; import org.jbpm.api.ProcessEngine; import org.jbpm.api.ProcessInstance; import org.jbpm.api.RepositoryService; import org.jbpm.api.TaskService; import org.jbpm.api.task.Task; /** base class for persistent jBPM tests. * * This class exposes a lot of extra convenience methods for testing * process executions. * * The ProcessEngine services will be initialized and available as * member fields. * * This test assumes that each test will clean the DB itself and that * no data is in the DB tables when the test finishes. * * During tearDown, a check will be done if all the DB tables are * empty. If not, that is logged with a F I X M E and the DB tables * are cleaned. * * @author Tom Baeyens * @author Heiko Braun */ public abstract class JbpmTestCase extends BaseJbpmTestCase { protected static ProcessEngine processEngine = null; protected static RepositoryService repositoryService; protected static ExecutionService executionService; protected static ManagementService managementService; protected static TaskService taskService; protected static HistoryService historyService; protected static IdentityService identityService; /** registered deployments. registered deployments will be deleted automatically * in the tearDown. This is a convenience function as each test is expected to clean up the DB. */ protected List registeredDeployments = new ArrayList(); protected void setUp() throws Exception { super.setUp(); initialize(); } protected synchronized void initialize() { if (processEngine==null) { processEngine = Configuration.getProcessEngine(); repositoryService = processEngine.get(RepositoryService.class); executionService = processEngine.getExecutionService(); historyService = processEngine.getHistoryService(); managementService = processEngine.getManagementService(); taskService = processEngine.getTaskService(); identityService = processEngine.getIdentityService(); } } protected void tearDown() throws Exception { deleteRegisteredDeployments(); String errorMsg = verifyDbClean(); super.tearDown(); if (errorMsg!=null) { if (exception==null) { throw new JbpmException(errorMsg); } else { throw new JbpmException(errorMsg, exception); } } } public static void jmsCreateQueue(String connectionFactoryJndiName, String queueJndiName) { JmsExtensions.createQueue(connectionFactoryJndiName, queueJndiName); } public static Object jmsConsumeMessageFromQueue(String connectionFactoryJndiName, String queueJndiName) { return jmsConsumeMessageFromQueue(connectionFactoryJndiName, queueJndiName, 1000, true, Session.AUTO_ACKNOWLEDGE); } public static Object jmsConsumeMessageFromQueue(String connectionFactoryJndiName, String queueJndiName, long timeout, boolean transacted, int acknowledgeMode) { return JmsExtensions.consumeMessageFromQueue(connectionFactoryJndiName, queueJndiName, timeout, transacted, acknowledgeMode); } public static Object jmsConsumeMessageFromQueueXA(String connectionFactoryJndiName, String queueJndiName, long timeout) { return JmsExtensions.consumeMessageFromQueueXA(connectionFactoryJndiName, queueJndiName, timeout); } public static void jmsAssertQueueEmpty(String connectionFactoryJndiName, String queueJndiName, long timeout, boolean transacted, int acknowledgeMode) { JmsExtensions.jmsAssertQueueEmpty(connectionFactoryJndiName, queueJndiName, timeout, transacted, acknowledgeMode); } public static void jmsAssertQueueEmptyXA(String connectionFactoryJndiName, String queueJndiName, long timeout) { JmsExtensions.jmsAssertQueueEmptyXA(connectionFactoryJndiName, queueJndiName, timeout); } public static void jmsRemoveQueue(String connectionFactoryJndiName, String queueJndiName) { JmsExtensions.removeQueue(connectionFactoryJndiName, queueJndiName); } public static void jmsCreateTopic(String connectionFactoryJndiName, String topicJndiName) { JmsExtensions.createTopic(connectionFactoryJndiName, topicJndiName); } public static JmsTopicListener jmsStartTopicListener(String connectionFactoryJndiName, String topicJndiName, boolean transacted, int acknowledgeMode) { return new JmsNonXATopicListener(connectionFactoryJndiName, topicJndiName, transacted, acknowledgeMode); } public static JmsTopicListener jmsStartTopicListenerXA(String connectionFactoryJndiName, String topicJndiName) { return new JmsXATopicListener(connectionFactoryJndiName, topicJndiName); } public static void jmsRemoveTopic(String connectionFactoryJndiName, String topicJndiName) { JmsExtensions.removeTopic(connectionFactoryJndiName, topicJndiName); } protected String verifyDbClean() { String errorMsg = null; String recordsLeftMsg = Db.verifyClean(processEngine); if ( (recordsLeftMsg!=null) && (recordsLeftMsg.length()>0) ) { errorMsg = "database was not clean after test: "+recordsLeftMsg; } return errorMsg; } protected void deleteRegisteredDeployments() { for (String deploymentId : registeredDeployments) { repositoryService.deleteDeploymentCascade(deploymentId); } } // deployment helper methods //////////////////////////////////////////////// /** deploys the process, keeps a reference to the deployment and * automatically deletes the deployment in the tearDown */ public String deployJpdlXmlString(String jpdlXmlString) { String deploymentDbid = repositoryService.createDeployment() .addResourceFromString("xmlstring.jpdl.xml", jpdlXmlString) .deploy(); registerDeployment(deploymentDbid); return deploymentDbid; } /** registered deployments will be deleted in the tearDown */ protected void registerDeployment(String deploymentId) { registeredDeployments.add(deploymentId); } // task helper methods ////////////////////////////////////////////////////// public static void assertContainsTask(List taskList, String taskName) { if (getTask(taskList, taskName)==null) { fail("tasklist doesn't contain task '"+taskName+"': "+taskList); } } public static void assertContainsTask(List taskList, String taskName, String assignee) { if (getTask(taskList, taskName, assignee)==null) { fail("tasklist doesn't contain task '"+taskName+"' for assignee '"+assignee+"': "+taskList); } } public static Task getTask(List taskList, String taskName) { for (Task task : taskList) { if (taskName.equals(task.getName())) { return task; } } return null; } public static Task getTask(List taskList, String taskName, String assignee) { for (Task task : taskList) { if (taskName.equals(task.getName())) { if (assignee==null) { if (task.getAssignee()==null) { return task; } } else { if (assignee.equals(task.getAssignee())) { return task; } } } } return null; } public void assertNoOpenTasks(String processInstanceId) { List tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list(); assertTrue("There were still open tasks found for the process instance with id " + processInstanceId + ". Current tasks are: " + listAllOpenTasks(processInstanceId), tasks.isEmpty()); } protected String listAllOpenTasks(String processInstanceId) { List tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list(); StringBuilder result = new StringBuilder(); for (Task task : tasks) { result.append("'" + task.getName() + "', "); } if (result.length() > 2) { result.setLength(result.length() - 2); // remove the last ', ' } return result.toString(); } // execution helper methods ////////////////////////////////////////// public void assertExecutionEnded(String processInstanceId) { assertNull("Error: an active process instance with id " + processInstanceId + " was found", executionService.findProcessInstanceById(processInstanceId)); } public void assertProcessInstanceEnded(String processInstanceId) { assertExecutionEnded(processInstanceId); } public void assertProcessInstanceEnded(ProcessInstance processInstance) { assertExecutionEnded(processInstance.getId()); } public void assertProcessInstanceActive(ProcessInstance processInstance) { assertProcessInstanceActive(processInstance.getId()); } public void assertProcessInstanceActive(String processInstanceId) { assertNotNull("Error: an active process instance with id " + processInstanceId + " was not found", executionService.findProcessInstanceById(processInstanceId)); } public void assertActivityActive(String executionId, String activityName) { assertTrue("The execution with id '" + executionId + "' is not active in the activity '" + activityName + "'." + "Current activitites are: " + listAllActiveActivites(executionId), executionService.findExecutionById(executionId).isActive(activityName)); } public void assertNotActivityActive(String executionId, String activityName) { Execution execution = executionService.findExecutionById(executionId); assertFalse(execution.isActive(activityName)); } public void assertActivitiesActive(String executionId, String ... activityNames) { for (String activityName : activityNames) { assertActivityActive(executionId, activityName); } } /** Checks if the given execution is active in one (or more) of the given activities */ public void assertExecutionInOneOrMoreActivitiesActive(String executionId, String ... activityNames) { boolean inOneActivityActive = false; Execution execution = executionService.findExecutionById(executionId); for (String activityName : activityNames) { if (execution.isActive(activityName)) { inOneActivityActive = true; } } assertTrue("The execution with id '" + executionId + "' is not active in one of these activities: " + activityNames + "Current activitites are: " + listAllActiveActivites(executionId), inOneActivityActive); } protected String listAllActiveActivites(String executionId) { Execution execution = executionService.findExecutionById(executionId); Set activeActivities = execution.findActiveActivityNames(); StringBuilder result = new StringBuilder(); for (String activeActivity : activeActivities) { result.append("'" + activeActivity + "', "); } if (result.length() > 2) { result.setLength(result.length() - 2); // remove the last ', ' } return result.toString(); } }