package org.activiti.crystalball.simulator;
/* 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.
*/
import org.activiti.crystalball.simulator.delegate.event.Function;
import org.activiti.crystalball.simulator.delegate.event.impl.DeploymentCreateTransformer;
import org.activiti.crystalball.simulator.delegate.event.impl.InMemoryRecordActivitiEventListener;
import org.activiti.crystalball.simulator.delegate.event.impl.ProcessInstanceCreateTransformer;
import org.activiti.crystalball.simulator.delegate.event.impl.UserTaskCompleteTransformer;
import org.activiti.crystalball.simulator.impl.*;
import org.activiti.crystalball.simulator.impl.clock.DefaultClockFactory;
import org.activiti.crystalball.simulator.impl.clock.ThreadLocalClock;
import org.activiti.crystalball.simulator.impl.playback.PlaybackUserTaskCompleteEventHandler;
import org.activiti.engine.*;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.el.NoExecutionVariableScope;
import org.activiti.engine.impl.util.DefaultClockImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.Clock;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.*;
import static org.junit.Assert.*;
/**
* @author martin.grofcik
*/
public class SimpleSimulationRunTest {
//deployment created
private static final String DEPLOYMENT_CREATED_EVENT_TYPE = "DEPLOYMENT_CREATED_EVENT";
private static final String DEPLOYMENT_RESOURCES_KEY = "deploymentResources";
// Process instance start event
private static final String PROCESS_INSTANCE_START_EVENT_TYPE = "PROCESS_INSTANCE_START";
private static final String PROCESS_DEFINITION_ID_KEY = "processDefinitionId";
private static final String VARIABLES_KEY = "variables";
// User task completed event
private static final String USER_TASK_COMPLETED_EVENT_TYPE = "USER_TASK_COMPLETED";
private static final String BUSINESS_KEY = "testBusinessKey";
public static final String TEST_VALUE = "TestValue";
public static final String TEST_VARIABLE = "testVariable";
private static final String USERTASK_PROCESS = "org/activiti/crystalball/simulator/impl/playback/PlaybackProcessStartTest.testUserTask.bpmn20.xml";
protected InMemoryRecordActivitiEventListener listener;
@Before
public void initListener() {
listener = new InMemoryRecordActivitiEventListener(getTransformers());
}
@After
public void cleanupListener() {
listener = null;
}
@Test
public void testStep() throws Exception {
recordEvents();
SimulationDebugger simDebugger = createDebugger();
simDebugger.init(new NoExecutionVariableScope());
RuntimeService runtimeService = SimulationRunContext.getRuntimeService();
TaskService taskService = SimulationRunContext.getTaskService();
HistoryService historyService = SimulationRunContext.getHistoryService();
// debuger step - deploy processDefinition
simDebugger.step();
step0Check(SimulationRunContext.getRepositoryService());
// debuger step - start process and stay on the userTask
simDebugger.step();
step1Check(runtimeService, taskService);
// debugger step - complete userTask and finish process
simDebugger.step();
step2Check(runtimeService, taskService);
checkStatus(historyService);
simDebugger.close();
ProcessEngines.destroy();
}
private void step2Check(RuntimeService runtimeService, TaskService taskService) {ProcessInstance procInstance = runtimeService.createProcessInstanceQuery().active().processInstanceBusinessKey("oneTaskProcessBusinessKey").singleResult();
assertNull(procInstance);
Task t = taskService.createTaskQuery().active().taskDefinitionKey("userTask").singleResult();
assertNull(t);
}
@Test
public void testRunToTime() throws Exception {
recordEvents();
SimulationDebugger simDebugger = createDebugger();
simDebugger.init(new NoExecutionVariableScope());
RuntimeService runtimeService = SimulationRunContext.getRuntimeService();
TaskService taskService = SimulationRunContext.getTaskService();
HistoryService historyService = SimulationRunContext.getHistoryService();
simDebugger.runTo(0);
ProcessInstance procInstance = runtimeService.createProcessInstanceQuery().active().processInstanceBusinessKey("oneTaskProcessBusinessKey").singleResult();
assertNull(procInstance);
// debuger step - deploy process
simDebugger.runTo(1);
step0Check(SimulationRunContext.getRepositoryService());
// debuger step - start process and stay on the userTask
simDebugger.runTo(1001);
step1Check(runtimeService, taskService);
// process engine should be in the same state as before
simDebugger.runTo(2000);
step1Check(runtimeService, taskService);
// debugger step - complete userTask and finish process
simDebugger.runTo(2500);
step2Check(runtimeService, taskService);
checkStatus(historyService);
simDebugger.close();
ProcessEngines.destroy();
}
@Test(expected = RuntimeException.class )
public void testRunToTimeInThePast() throws Exception {
recordEvents();
SimulationDebugger simDebugger = createDebugger();
simDebugger.init(new NoExecutionVariableScope());
try {
simDebugger.runTo(-1);
fail("RuntimeException expected - unable to execute event from the past");
} finally {
simDebugger.close();
ProcessEngines.destroy();
}
}
@Test
public void testRunToEvent() throws Exception {
recordEvents();
SimulationDebugger simDebugger = createDebugger();
simDebugger.init(new NoExecutionVariableScope());
try {
simDebugger.runTo(USER_TASK_COMPLETED_EVENT_TYPE);
step1Check(SimulationRunContext.getRuntimeService(), SimulationRunContext.getTaskService());
simDebugger.runContinue();
} finally {
simDebugger.close();
ProcessEngines.destroy();
}
}
@Test(expected = RuntimeException.class)
public void testRunToNonExistingEvent() throws Exception {
recordEvents();
SimulationDebugger simDebugger = createDebugger();
simDebugger.init(new NoExecutionVariableScope());
try {
simDebugger.runTo("");
checkStatus(SimulationRunContext.getHistoryService());
} finally {
simDebugger.close();
ProcessEngines.destroy();
}
}
private void step0Check(RepositoryService repositoryService) {
Deployment deployment;
deployment = repositoryService.createDeploymentQuery().singleResult();
assertNotNull(deployment);
}
private void step1Check(RuntimeService runtimeService, TaskService taskService) {ProcessInstance procInstance;
procInstance = runtimeService.createProcessInstanceQuery().active().processInstanceBusinessKey("oneTaskProcessBusinessKey").singleResult();
assertNotNull(procInstance);
Task t = taskService.createTaskQuery().active().taskDefinitionKey("userTask").singleResult();
assertNotNull(t);
}
@Test
public void testRunContinue() throws Exception {
recordEvents();
SimulationDebugger simDebugger = createDebugger();
simDebugger.init(new NoExecutionVariableScope());
simDebugger.runContinue();
checkStatus(SimulationRunContext.getHistoryService());
simDebugger.close();
ProcessEngines.destroy();
}
private SimulationDebugger createDebugger() {
final SimpleSimulationRun.Builder builder = new SimpleSimulationRun.Builder();
// init simulation run
Clock clock = new ThreadLocalClock(new DefaultClockFactory());
ProcessEngineConfigurationImpl config = (ProcessEngineConfigurationImpl) ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault();
config.setClock(clock);
SimulationProcessEngineFactory simulationProcessEngineFactory = new SimulationProcessEngineFactory(config);
builder.processEngine(simulationProcessEngineFactory.getObject())
.eventCalendar((new SimpleEventCalendarFactory(clock, new SimulationEventComparator(), listener.getSimulationEvents())).getObject())
.eventHandlers(getHandlers());
return builder.build();
}
private void checkStatus(HistoryService historyService) {
final HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().
finished().
singleResult();
assertNotNull(historicProcessInstance);
assertEquals("oneTaskProcessBusinessKey", historicProcessInstance.getBusinessKey());
HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskDefinitionKey("userTask").singleResult();
assertEquals("user1", historicTaskInstance.getAssignee());
}
private void recordEvents() {
Clock clock = new DefaultClockImpl();
clock.setCurrentTime(new Date(0));
ProcessEngineConfigurationImpl config = (ProcessEngineConfigurationImpl) ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault();
config.setClock(clock);
ProcessEngine processEngine = (new RecordableProcessEngineFactory(config, listener))
.getObject();
processEngine.getRepositoryService().createDeployment().
addClasspathResource(USERTASK_PROCESS).
deploy();
EventRecorderTestUtils.increaseTime(clock);
TaskService taskService = processEngine.getTaskService();
Map<String, Object> variables = new HashMap<String, Object>();
variables.put(TEST_VARIABLE, TEST_VALUE);
processEngine.getRuntimeService().startProcessInstanceByKey("oneTaskProcess", "oneTaskProcessBusinessKey", variables);
EventRecorderTestUtils.increaseTime(clock);
Task task = taskService.createTaskQuery().taskDefinitionKey("userTask").singleResult();
taskService.complete(task.getId());
checkStatus(processEngine.getHistoryService());
EventRecorderTestUtils.closeProcessEngine(processEngine, listener);
ProcessEngines.destroy();
}
private List<Function<ActivitiEvent, SimulationEvent>> getTransformers() {
List<Function<ActivitiEvent, SimulationEvent>> transformers = new ArrayList<Function<ActivitiEvent, SimulationEvent>>();
transformers.add(new DeploymentCreateTransformer(DEPLOYMENT_CREATED_EVENT_TYPE, DEPLOYMENT_RESOURCES_KEY));
transformers.add(new ProcessInstanceCreateTransformer(PROCESS_INSTANCE_START_EVENT_TYPE, PROCESS_DEFINITION_ID_KEY, BUSINESS_KEY, VARIABLES_KEY));
transformers.add(new UserTaskCompleteTransformer(USER_TASK_COMPLETED_EVENT_TYPE));
return transformers;
}
public static Map<String, SimulationEventHandler> getHandlers() {
Map<String, SimulationEventHandler> handlers = new HashMap<String, SimulationEventHandler>();
handlers.put(DEPLOYMENT_CREATED_EVENT_TYPE, new DeployResourcesEventHandler(DEPLOYMENT_RESOURCES_KEY));
handlers.put(PROCESS_INSTANCE_START_EVENT_TYPE, new StartProcessByIdEventHandler(PROCESS_DEFINITION_ID_KEY, BUSINESS_KEY, VARIABLES_KEY));
handlers.put(USER_TASK_COMPLETED_EVENT_TYPE, new PlaybackUserTaskCompleteEventHandler());
return handlers;
}
}