package betsy.bpmn; import java.nio.file.Path; import betsy.bpmn.engines.AbstractBPMNEngine; import betsy.bpmn.model.BPMNProcess; import betsy.bpmn.model.BPMNTestSuite; import betsy.bpmn.reporting.BPMNCsvReport; import betsy.bpmn.reporting.BPMNReporter; import betsy.common.analytics.Analyzer; import betsy.common.tasks.FileTasks; import betsy.common.util.IOCapture; import betsy.common.util.LogUtil; import betsy.common.util.Progress; import org.apache.log4j.Logger; import org.apache.log4j.MDC; import org.codehaus.groovy.runtime.StackTraceUtils; import pebl.builder.Aggregator; import pebl.builder.Builder; import pebl.builder.PEBLEngineAdder; import pebl.builder.PEBLPerformanceResultsAdder; import pebl.builder.PEBLTestResultsEnricher; import pebl.xsd.PEBL; import static betsy.common.config.Configuration.get; public class BPMNComposite { private static final Logger LOGGER = Logger.getLogger(BPMNComposite.class); private BPMNTestSuite testSuite; private LogUtil logUtil; protected void log(String name, Runnable closure) { logUtil.log(name, LOGGER, closure); } protected void log(Path path, Runnable closure) { logUtil.log(path, LOGGER, closure); } public void execute() { final Progress progress = new Progress(testSuite.getProcessesCount()); logUtil = new LogUtil(testSuite); MDC.put("progress", progress.toString()); // prepare test suite // MUST BE OUTSITE OF LOG -> as it deletes whole file tree FileTasks.deleteDirectory(testSuite.getPath()); FileTasks.mkdirs(testSuite.getPath()); log(testSuite.getPath(), () -> { // fail fast for (AbstractBPMNEngine engine : testSuite.getEngines()) { checkRunning(engine); } for (AbstractBPMNEngine engine : testSuite.getEngines()) { FileTasks.mkdirs(engine.getPath()); log(engine.getPath(), () -> { for (BPMNProcess process : engine.getProcesses()) { progress.next(); MDC.put("progress", progress.toString()); try{ executeProcess(process); } catch (Exception e) { if(get("continue.on.exception").contains("true")){ Throwable cleanedException = StackTraceUtils.deepSanitize(e); LOGGER.error("something went wrong during execution", cleanedException); }else{ throw e; } } } }); } createReports(); }); } protected void checkRunning(AbstractBPMNEngine engine) { if (engine.isRunning()) { throw new IllegalStateException("EngineExtended " + engine.getName() + " is running"); } } protected void createReports() { log(testSuite.getReportsPath(), () -> { new BPMNReporter(testSuite).createReports(); new Analyzer(testSuite.getCsvFilePath(), testSuite.getReportsPath()).createAnalytics(new BPMNCsvReport()); PEBL pebl = Builder.getPebl(); PEBLEngineAdder.addEngines(pebl); PEBLPerformanceResultsAdder.addPerformanceResults(pebl); new PEBLTestResultsEnricher().addTestResults(testSuite, pebl); new Aggregator().computeFeatureResults(pebl); pebl.writeTo(testSuite.getPath()); }); } protected void executeProcess(final BPMNProcess process) { log(process.getTargetPath(), () -> { buildPackageAndTest(process); try { install(process); start(process); deploy(process); test(process); } catch (IllegalStateException e) { LOGGER.error("Test case " + process.getName() + " crashed", e); } finally { // always try to collect log files try { collect(process); } catch(IllegalStateException ignore){ // not being able to store the logs should not crash the build } // ensure shutdown shutdown(process); } }); } protected void shutdown(final BPMNProcess process) { log(process.getTargetPath().resolve("engine_shutdown"), () -> process.getEngine().shutdown()); } protected void deploy(final BPMNProcess process) { log(process.getTargetPath().resolve("deploy"), () -> process.getEngine().deploy(process.getName(), process.getDeploymentPackagePath())); } protected void start(final BPMNProcess process) { log(process.getTargetPath().resolve("engine_startup"), () -> process.getEngine().startup()); } protected void install(BPMNProcess process) { log(process.getTargetPath().resolve("engine_install"), () -> process.getEngine().install()); } protected void test(final BPMNProcess process) { log(process.getTargetPath().resolve("test"), () -> process.getEngine().testProcess(process)); } protected void collect(final BPMNProcess process) { log(process.getTargetPath().resolve("collect"), () -> process.getEngine().storeLogs(process.getTargetLogsPath())); } protected void buildPackageAndTest(final BPMNProcess process) { log(process.getTargetPath().resolve("build"), () -> { buildPackage(process); buildTest(process); }); } protected void buildTest(final BPMNProcess process) { log(process.getTargetPath().resolve("build_test"), () -> IOCapture.captureIO(() -> process.getEngine().buildTest(process))); } protected void buildPackage(final BPMNProcess process) { log(process.getTargetPath().resolve("build_package"), () -> IOCapture.captureIO(() -> { Path path = process.getEngine().buildArchives(process); process.setDeploymentPackagePath(path); })); } public BPMNTestSuite getTestSuite() { return testSuite; } public void setTestSuite(BPMNTestSuite testSuite) { this.testSuite = testSuite; } }