/*
* Copyright (c) NASK, NCSC
*
* This file is part of HoneySpider Network 2.1.
*
* This is a free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package pl.nask.hsn2.workflow.engine;
import java.util.Collections;
import org.activiti.engine.impl.pvm.PvmProcessDefinition;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import pl.nask.hsn2.MockedBus;
import pl.nask.hsn2.activiti.AbstractActivitiTest;
import pl.nask.hsn2.activiti.ActivitiWorkflowBuilder;
import pl.nask.hsn2.activiti.BehaviorFactory;
import pl.nask.hsn2.activiti.BehaviorFactoryImpl;
import pl.nask.hsn2.bus.api.BusManager;
import pl.nask.hsn2.bus.operations.ObjectData;
import pl.nask.hsn2.bus.operations.TaskRequest;
import pl.nask.hsn2.framework.suppressor.SingleThreadTasksSuppressor;
import pl.nask.hsn2.framework.workflow.engine.ProcessBasedWorkflowDescriptor;
import pl.nask.hsn2.framework.workflow.hwl.Output;
import pl.nask.hsn2.framework.workflow.hwl.ProcessDefinition;
import pl.nask.hsn2.framework.workflow.hwl.Service;
import pl.nask.hsn2.framework.workflow.hwl.Workflow;
import pl.nask.hsn2.framework.workflow.job.WorkflowJobInfo;
import pl.nask.hsn2.utils.AtomicLongIdGenerator;
@Test(enabled=true)
public class HwlOutputWaitTest extends AbstractActivitiTest {
private MockedBus myBus;
@BeforeClass
public void prepareTestClass() {
myBus = new MockedBus();
BusManager.setBus(myBus);
}
@BeforeMethod
public void prepareTest() {
myBus.requests.clear();
}
public void serviceWithSimpleOutput() throws Exception {
ProcessBasedWorkflowDescriptor<PvmProcessDefinition> wdf = buildWorkflowDefinition(null);
SingleThreadTasksSuppressor suppressor = new SingleThreadTasksSuppressor(true);
ActivitiWorkflowEngine engine = new ActivitiWorkflowEngine(new AtomicLongIdGenerator(), suppressor, 1);
long jobId = engine.startJob(wdf);
engine.resume(jobId);
WorkflowJobInfo jobInfo = engine.getJobInfo(jobId);
Assert.assertFalse(jobInfo.isEnded(), "job should be running and waiting for TaskCompleted");
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 0, "job shoud have no subprocesses running");
// trigger creation of a subprocess
TaskRequest req = myBus.requests.take();
int taskId = req.getTaskId();
engine.taskCompleted(jobId, taskId, Collections.singleton(1000L));
// subprocesses should be created
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 1, "one subprocess should be running");
// terminate subprocess
req = myBus.requests.take();
engine.taskCompleted(jobId, req.getTaskId(), null);
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 0, "job shoud have no subprocesses running");
Assert.assertTrue(jobInfo.isEnded(), "job should be ended");
}
public void recursiveOutput() throws Exception {
ProcessBasedWorkflowDescriptor<PvmProcessDefinition> wdf = buildWorkflowDefinition(null);
SingleThreadTasksSuppressor suppressor = new SingleThreadTasksSuppressor(true);
ActivitiWorkflowEngine engine = new ActivitiWorkflowEngine(new AtomicLongIdGenerator(), suppressor, 1);
long jobId = engine.startJob(wdf);
engine.resume(jobId);
WorkflowJobInfo jobInfo = engine.getJobInfo(jobId);
Assert.assertFalse(jobInfo.isEnded(), "job should be running and waiting for TaskCompleted");
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 0, "job shoud have no subprocesses running");
// trigger creation of a subproces
TaskRequest req = myBus.requests.take();
int taskId = req.getTaskId();
engine.taskCompleted(jobId, taskId, Collections.singleton(1000L));
// subprocesses should be created
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 1, "one subprocess should be running");
// trigger creation of sub-subprocess
req = myBus.requests.take();
taskId = req.getTaskId();
engine.taskCompleted(jobId, taskId, Collections.singleton(1001L));
// subprocess should be created
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 2, "2 subprocesses should be running");
// terminate subprocess
req = myBus.requests.take();
engine.taskCompleted(jobId, req.getTaskId(), null);
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 0, "job shoud have no subprocesses running");
Assert.assertTrue(jobInfo.isEnded(), "job should be ended");
}
public void outputConditionFalse() throws Exception {
ProcessBasedWorkflowDescriptor<PvmProcessDefinition> wdf = buildWorkflowDefinition("id==1000");
SingleThreadTasksSuppressor suppressor = new SingleThreadTasksSuppressor(true);
ActivitiWorkflowEngine engine = new ActivitiWorkflowEngine(new AtomicLongIdGenerator(), suppressor, 1);
long jobId = engine.startJob(wdf);
engine.resume(jobId);
WorkflowJobInfo jobInfo = engine.getJobInfo(jobId);
Assert.assertFalse(jobInfo.isEnded(), "job should be running and waiting for TaskCompleted");
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 0, "job shoud have no subprocesses running");
ObjectData obj = new ObjectData();
obj.setId(1001L);
myBus.addObject(1001L, obj );
// trigger creaction of a subproces
TaskRequest req = myBus.requests.take();
int taskId = req.getTaskId();
engine.taskCompleted(jobId, taskId, Collections.singleton(1001L));
// subprocesses should be created
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 0, "condition should resolve to false, output should not creata a subprocess");
Assert.assertTrue(jobInfo.isEnded(), "job should be ended");
}
public void outputConditionTrue() throws Exception {
ProcessBasedWorkflowDescriptor<PvmProcessDefinition> wdf = buildWorkflowDefinition("id==1000");
SingleThreadTasksSuppressor suppressor = new SingleThreadTasksSuppressor(true);
ActivitiWorkflowEngine engine = new ActivitiWorkflowEngine(new AtomicLongIdGenerator(), suppressor, 1);
long jobId = engine.startJob(wdf);
engine.resume(jobId);
WorkflowJobInfo jobInfo = engine.getJobInfo(jobId);
Assert.assertFalse(jobInfo.isEnded(), "job should be running and waiting for TaskCompleted");
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 0, "job shoud have no subprocesses running");
// trigger creaction of a subproces
TaskRequest req = myBus.requests.take();
ObjectData obj = new ObjectData();
obj.setId(1000L);
myBus.addObject(1000L, obj );
int taskId = req.getTaskId();
engine.taskCompleted(jobId, taskId, Collections.singleton(1000L));
// subprocesses should be created
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 1, "output condition should resolve to true, so one process should be created");
// terminate subprocess
req = myBus.requests.take();
engine.taskCompleted(jobId, req.getTaskId(), null);
Assert.assertEquals(jobInfo.getActiveSubtasksCount(), 0, "job shoud have no subprocesses running");
Assert.assertTrue(jobInfo.isEnded(), "job should be ended");
}
private ProcessBasedWorkflowDescriptor<PvmProcessDefinition> buildWorkflowDefinition(String conditionForOutput) {
ProcessDefinition mainDef = new ProcessDefinition("main");
Service mainService = new Service("mainService");
mainService.addOutput(new Output("subprocess", conditionForOutput));
mainDef.addExecutionPoint(mainService);
ProcessDefinition subprocess= new ProcessDefinition("subprocess");
Service subService = new Service("subservice");
subService.addOutput(new Output("subprocess", conditionForOutput));
subprocess.addExecutionPoint(subService);
Workflow workflow= new Workflow("testWorkflow");
workflow.addProcess(mainDef );
workflow.addProcess(subprocess);
BehaviorFactory behaviorFactory = new BehaviorFactoryImpl();
ActivitiWorkflowBuilder builder = new ActivitiWorkflowBuilder(behaviorFactory );
builder.buildWorkflow(workflow);
ProcessBasedWorkflowDescriptor<PvmProcessDefinition> wdf = new ProcessBasedWorkflowDescriptor<PvmProcessDefinition>("w1", "w1", workflow);
wdf.setProcessDefinitionRegistry(builder.getRegistry());
return wdf;
}
}