package org.simantics.tests.modelled.ui; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.swt.graphics.Image; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.layer0.Layer0; import org.simantics.scl.compiler.module.coverage.CombinedCoverage; import org.simantics.scl.runtime.SCLContext; import org.simantics.scl.runtime.reporting.AbstractSCLReportingHandler; import org.simantics.scl.runtime.reporting.SCLReportingHandler; import org.simantics.tests.modelled.ontology.TestsResource; import org.simantics.tests.modelled.utils.ModelledSTSSuite; import org.simantics.tests.modelled.utils.ModelledSTSTest; import org.simantics.tests.modelled.utils.ModelledSTSTest.CommandSessionVariable; import org.simantics.tests.modelled.utils.STSSuiteTestCollector; public class STSTestSuiteModel { private Map> storedVars = new HashMap<>(); class STSTest { private final ModelledSTSTest test; private final STSSuite parent; private boolean executed = false; private long duration; private boolean failed = false; private boolean isRunning = false; private List output = new ArrayList<>(); public STSTest(ModelledSTSTest test, STSSuite parent) { this.test = test; this.parent = parent; } public String getName() { return test.getName(); } public String getLabel() { StringBuilder sb = new StringBuilder(); sb.append(getName()); if (executed || failed) sb.append(" (").append(duration).append(" ms)"); return sb.toString(); } public String getDefinition() { return test.getCode(); } public STSSuite getParent() { return parent; } public void execute() { isRunning = true; long start = System.currentTimeMillis(); Object old = SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER); try { if (parent != null) parent.startedCount++; SCLContext.getCurrent().put(SCLReportingHandler.REPORTING_HANDLER, new AbstractSCLReportingHandler() { @Override public void print(String text) { appendOutput(text + "\n"); } @Override public void printCommand(String command) { appendOutput("> " + command + "\n"); } @Override public void printError(String error) { appendOutput(error + "\n"); } }); List resolvedVars = new ArrayList<>(); for (String deps : test.getDependencies()) { List vars = storedVars.get(deps); if (vars != null) resolvedVars.addAll(vars); } List vars = test.run(resolvedVars); storedVars.put(test.getName(), vars); executed = true; } catch (Throwable t) { t.printStackTrace(); if (parent != null) parent.failureCount++; failed = true; } finally { isRunning = false; long end = System.currentTimeMillis(); duration = end - start; SCLContext.getCurrent().put(SCLReportingHandler.REPORTING_HANDLER, old); } } protected void appendOutput(String text) { output.add(text); } public List getOutput() { return output; } public void setCoverage(CombinedCoverage coverage) { test.setCoverage(coverage); } public CombinedCoverage getCoverage() { return test.getCoverage(); } public int getPriority() { return test.getPriority(); } @Override public String toString() { return getName() + " [priority=" + getPriority() + ", executed=" + executed + ", duration=" + duration + "]"; } public boolean isIgnored() { return test.isIgnored(); } } class STSSuite { private ModelledSTSSuite suite; private STSTest[] children; private int startedCount; private int errorCount; private int failureCount; public int ignoredCount; public STSSuite(ModelledSTSSuite suite) { this.suite = suite; } public STSTest[] getChildren() { if (children == null) children = suite.getSortedChildren().stream().map(modelledTest -> new STSTest(modelledTest, this)).collect(Collectors.toList()).toArray(new STSTest[suite.getChildren().size()]); return children; } public String getName() { return suite.getName(); } public String getLabel() { StringBuilder sb = new StringBuilder(); sb.append(getName()); long totalTime = 0; if (getChildren() != null) { for (STSTest test : getChildren()) { if (test.executed || test.failed) { totalTime += test.duration; } } } if (totalTime != 0) sb.append(" (").append(totalTime).append(" ms)"); return sb.toString(); } public boolean isRunning() { if (getChildren() != null) { for (STSTest test: getChildren()) { if (test.isRunning) { return true; } } } return false; } public boolean executed() { if (getChildren() != null) { for (STSTest test: getChildren()) { if (!test.executed) { return false; } } } return true; } public boolean failed() { if (getChildren() != null) { for (STSTest test: getChildren()) { if (test.failed) { return true; } } } return false; } public CombinedCoverage getCoverage() { return suite.getCoverage(); } } private STSSuite suite; private STSTest test; private final List listeners = new ArrayList<>(); private Job currentJob; public STSTestSuiteModel() { } public void addListener(STSExecutionListener listener) { listeners.add(listener); } public void removeListener(STSExecutionListener listener) { listeners.remove(listener); } public Object[] getElements() { if (suite != null) return new Object[] {suite}; else if (test != null) return new Object[] {test}; else return null; } public void execute() { String command; if (suite != null) command = suite.getName(); else command = test.getName(); if (currentJob != null) currentJob.cancel(); currentJob = new Job(command) { @Override protected IStatus run(IProgressMonitor monitor) { if (suite != null) { executeSuite(); } else if (test != null) { executeTest(); } return Status.OK_STATUS; } @Override protected void canceling() { Thread thread = getThread(); if(thread != null) thread.interrupt(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } thread = getThread(); if(thread != null) thread.stop(); } }; currentJob.schedule(); } public void interrupt() { if (currentJob != null) currentJob.cancel(); } private void testExecuted() { listeners.forEach(listener -> { listener.testExecuted(); }); } private void executeSuite() { for (STSTest test : suite.getChildren()) { if (test.isIgnored()) { testExecuted(); test.getParent().ignoredCount++; continue; } test.execute(); testExecuted(); } } private void executeTest() { test.execute(); testExecuted(); } public boolean hasChildren(Object element) { if (element instanceof STSTest) { return false; } else if (element instanceof STSSuite) { STSSuite suite = (STSSuite) element; return (suite.getChildren() != null ? suite.getChildren().length > 0 : false); } else { throw new IllegalArgumentException(element.toString()); } } public Object getParent(Object element) { if (element instanceof STSTest) { return ((STSTest) element).getParent(); } else if (element instanceof STSSuite) { return null; } else { throw new IllegalArgumentException(element.toString()); } } public Object[] getChildren(Object parentElement) { if (parentElement instanceof STSTest) { return null; } else if (parentElement instanceof STSSuite) { STSSuite suite = (STSSuite) parentElement; return suite.getChildren(); } else { throw new IllegalArgumentException(parentElement.toString()); } } public String getText(Object element) { if (element instanceof STSTest) return ((STSTest)element).getLabel(); else if (element instanceof STSSuite) return ((STSSuite)element).getLabel(); else throw new IllegalArgumentException(element.toString()); } public Image getImage(Object element) { if (element instanceof STSSuite) { STSSuite suite = (STSSuite) element; if (suite.isRunning()) return STSTestSuiteProvider.suiteRunningIcon; else if (suite.executed()) return STSTestSuiteProvider.suiteOkIcon; else if (suite.failed()) return STSTestSuiteProvider.suiteFailIcon; else return STSTestSuiteProvider.suiteIcon; } else if (element instanceof STSTest) { STSTest test = (STSTest) element; if (test.isRunning) return STSTestSuiteProvider.testRunningIcon; else if (test.executed) return STSTestSuiteProvider.testOkIcon; else if (test.failed) return STSTestSuiteProvider.testFailIcon; else return STSTestSuiteProvider.testIcon; } return null; } public void updateInput(Resource root) { suite = null; test = null; try { Simantics.getSession().syncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); TestsResource TESTS = TestsResource.getInstance(graph); if (graph.isInstanceOf(root, TESTS.STSTest)) { test = new STSTest(STSSuiteTestCollector.toModelledTest(graph, root), null); } else if (graph.isInstanceOf(root, TESTS.STSSuite)) { List tests = new ArrayList<>(); for (Resource test : graph.getObjects(root, L0.ConsistsOf)) tests.add(STSSuiteTestCollector.toModelledTest(graph, test)); suite = new STSSuite(STSSuiteTestCollector.toModelledSuite(graph, root, tests)); } else { throw new IllegalArgumentException(root.toString()); } } }); } catch (DatabaseException e) { e.printStackTrace(); } } public List getOutput(Object element) { if (element instanceof STSTest) { STSTest test = (STSTest) element; return test.getOutput(); } return Collections.emptyList(); } public int getStartedCount() { if (suite != null) return suite.startedCount; else return 0; } public int getIgnoredCount() { if (suite != null) return suite.ignoredCount; return 0; } public int getTotalCount() { if (suite != null && suite.getChildren() != null) return suite.getChildren().length; else if (test != null) return 1; else return 0; } public int getErrorCount() { if (suite != null) return suite.errorCount; return 0; } public int getFailureCount() { if (suite != null) return suite.failureCount; return 0; } public int getAssumptionFailureCount() { return 0; } public boolean isStopped() { if (suite != null) return !suite.isRunning(); else return test.isRunning; } }