/* * 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.activiti; import java.util.ArrayList; import java.util.List; import java.util.Map; import junit.framework.Assert; import mockit.Mocked; import org.activiti.engine.impl.pvm.PvmExecution; import org.activiti.engine.impl.pvm.PvmProcessDefinition; import org.activiti.engine.impl.pvm.PvmProcessInstance; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.impl.pvm.runtime.ExecutionImpl; import org.testng.AssertJUnit; import org.testng.annotations.BeforeMethod; import pl.nask.hsn2.bus.api.BusManager; import pl.nask.hsn2.bus.connector.objectstore.ObjectStoreConnector; import pl.nask.hsn2.bus.connector.process.ProcessConnector; import pl.nask.hsn2.bus.connector.process.StubProcessConnector; import pl.nask.hsn2.bus.operations.JobStatus; import pl.nask.hsn2.framework.bus.FrameworkBus; import pl.nask.hsn2.framework.suppressor.SingleThreadTasksSuppressor; import pl.nask.hsn2.suppressor.JobSuppressorHelperImpl; import pl.nask.hsn2.workflow.engine.ExecutionWrapper; public class AbstractActivitiTest { private long freeMem; private long totalMem; private long maxMem; private long usedMem; protected PvmProcessFactory pvmFactory = null; @Mocked private ObjectStoreConnector connector ; @BeforeMethod void prepare() { if (pvmFactory == null) { BusManager.setBus(new FrameworkBus() { public ObjectStoreConnector getObjectStoreConnector() { return connector; } public ProcessConnector getProcessConnector() { return new StubProcessConnector(); } @Override public void start() { } @Override public void stop() { } @Override public boolean isRunning() { return true; } @Override public void jobStarted(long jobId) { } @Override public void jobFinished(long jobId, JobStatus status) { } @Override public void jobFinishedReminder(long jobId, JobStatus status, int offendingTask) {} @Override public void releaseResources() {} }); pvmFactory = new PvmProcessFactory(); } } public static void assertProcessState( PvmProcessInstance instance, String activityName) { try { AssertJUnit.assertEquals(activityName, instance.getActivity().getId()); } catch (AssertionError e) { stats(instance); throw e; } } public static void assertEnded(PvmProcessInstance instance) { try { AssertJUnit.assertTrue(instance.isEnded()); } catch (AssertionError e) { stats(instance); throw e; } } public static void assertNotEnded(PvmProcessInstance instance) { try { AssertJUnit.assertFalse(instance.isEnded()); } catch (AssertionError e) { stats(instance); throw e; } } public static void assertActive(PvmProcessInstance instance, int numberOfActive) { List<String> active = instance.findActiveActivityIds(); try { AssertJUnit.assertEquals(numberOfActive, active.size()); } catch (AssertionError e) { stats(instance); throw e; } } protected void printMemStats(String msg) { long free = Runtime.getRuntime().freeMemory(); long total = Runtime.getRuntime().totalMemory(); long max = Runtime.getRuntime().maxMemory(); long used = total - free; System.out.printf("%s: Mem used %,d (%,d), free %,d (%,d), total %,d (%,d), max %,d (%,d)\n", msg, used, (used - usedMem), free, (free - freeMem), total, (total - totalMem), max, (max - maxMem)); this.freeMem = free; this.totalMem = total; this.maxMem = max; this.usedMem = used; } public void testMultipleInstancesPerformance(String message, PvmProcessDefinition def) { testMultipleInstancesPerformance(message, def, null); } public void testMultipleInstancesPerformance(String message, PvmProcessDefinition def, Map<String, Object> variables) { System.out.println(message + " : testMultipleInstancesPerformance"); List<PvmProcessInstance> instances = new ArrayList<PvmProcessInstance>(5000); for (int i=0; i<5000; i++) { PvmProcessInstance instance = def.createProcessInstance(); ExecutionWrapper wrapper = new ExecutionWrapper(instance); wrapper.initProcessState(i, new JobSuppressorHelperImpl(1L, 100, new SingleThreadTasksSuppressor(true))); setVariables(instance, variables); instances.add(instance); } printMemStats("instancesCreated"); for (PvmProcessInstance pi: instances) { pi.start(); pi.signal("resume", null); } printMemStats("instancesStarted"); List<PvmProcessInstance> activeProcesses = new ArrayList<PvmProcessInstance>(instances); List<PvmProcessInstance> processed = new ArrayList<PvmProcessInstance>(); int i = 0; do { i++; for (PvmProcessInstance pi: activeProcesses) { if (!pi.isEnded()) { signalActiveExecution(pi); processed.add(pi); } } activeProcesses = new ArrayList<PvmProcessInstance>(processed); processed = new ArrayList<PvmProcessInstance>(); printMemStats("signal " + i); } while (activeProcesses.size() > 0); for (PvmProcessInstance pi: instances) { try { AssertJUnit.assertTrue(pi.isEnded()); } catch (AssertionError e) { stats(pi); throw e; } pi.deleteCascade("end"); } printMemStats("ending"); } private void setVariables(PvmProcessInstance instance, Map<String, Object> variables) { if (variables != null) { for (Map.Entry<String, Object> e: variables.entrySet()) { instance.setVariable(e.getKey(), e.getValue()); } } } protected void signalAllActiveExecutions(PvmProcessInstance instance) { List<String> active = instance.findActiveActivityIds(); for (int i = active.size(); i > 0; i--) { instance.findExecution(active.get(i - 1)).signal("completeTask", null); } } protected void signalActiveExecution(PvmProcessInstance pi) { getActiveExecution(pi).signal("completeTask", null); } protected void signalNamedExecution(PvmProcessInstance pi, String activityId, String signalName) { PvmExecution exec = pi.findExecution(activityId); if (exec != null) { exec.signal(signalName, null); } else { stats(pi); Assert.fail(String.format("Skipping signal: %s, there is no activity %s in %s\n", signalName, activityId, pi)); } } protected void signalActiveExecution(PvmProcessInstance pi, String signalName) { getActiveExecution(pi).signal(signalName, null); } protected void signalActiveExecution(PvmProcessInstance pi, String signalName, Object signalData) { getActiveExecution(pi).signal(signalName, signalData); } protected static void stats(String prefix, PvmExecution exec) { stats(prefix, (ExecutionImpl) exec); } protected static void stats(PvmExecution exec) { stats("", (ExecutionImpl) exec); } private static void stats(String prefix, ExecutionImpl pi) { if (pi == null) return; List<String> ids = pi.findActiveActivityIds(); System.out.printf("\n%sProcessInstance: %s with activeActivityIds: %s\n", prefix, pi, ids); List<ExecutionImpl> executions = pi.getExecutions(); System.out.printf("%sExecutions: %s\n", prefix, executions); for (PvmExecution exec: executions) { stats(" " + prefix, exec); } System.out.printf("%sVariables: %s\n", prefix, pi.getVariables()); System.out.printf("%sSubProcess: \n", prefix); stats(" " + prefix, pi.getSubProcessInstance()); System.out.printf("%sSubexecutions: \n", prefix); @SuppressWarnings("unchecked") List <PvmExecution> children = (List<PvmExecution>) pi.getVariable("child_executions"); System.out.printf("%sManagedProcesses: %s\n", prefix, children); if (children != null) { for (PvmExecution exec: children) stats(" " + prefix, exec); } System.out.printf("%sParent Process: %s\n", prefix, pi.getVariable("parent_execution")); System.out.printf("%sProcessDefinition: %s\n", prefix, pi.getProcessDefinition()); List<ActivityImpl> activities = pi.getProcessDefinition().getActivities(); System.out.printf("%sProcessDefinition.activities: [", prefix); for (ActivityImpl act: activities) { System.out.printf("%s (%s), " , act.getId(), act.getActivityBehavior()); } System.out.println("]"); System.out.printf("%sProcessState.ended: %s\n", prefix, pi.isEnded()); } protected PvmExecution getActiveExecution(PvmProcessInstance pi) { List<String> ids = pi.findActiveActivityIds(); System.out.println("Active executions: " + ids); AssertJUnit.assertTrue(ids.size() > 0); return pi.findExecution(ids.get(ids.size() - 1)); } }