+package org.simantics.tests.modelled.ui;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.StringReader;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.regex.Pattern;\r
+import java.util.regex.PatternSyntaxException;\r
+\r
+import org.eclipse.swt.graphics.Image;\r
+import org.simantics.Simantics;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.scl.compiler.commands.CommandSession;\r
+import org.simantics.scl.compiler.commands.TestScriptExecutor;\r
+import org.simantics.scl.compiler.module.Module;\r
+import org.simantics.scl.compiler.module.coverage.CombinedCoverage;\r
+import org.simantics.scl.compiler.module.coverage.CoverageBuilder;\r
+import org.simantics.scl.compiler.module.coverage.CoverageUtils;\r
+import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;\r
+import org.simantics.scl.compiler.module.options.ModuleCompilationOptionsAdvisor;\r
+import org.simantics.scl.compiler.module.repository.ModuleRepository;\r
+import org.simantics.scl.compiler.runtime.RuntimeModule;\r
+import org.simantics.scl.osgi.SCLOsgi;\r
+import org.simantics.scl.runtime.reporting.AbstractSCLReportingHandler;\r
+import org.simantics.tests.modelled.ontology.TestsResource;\r
+\r
+public class STSTestSuiteModel {\r
+\r
+ static class STSTest {\r
+ \r
+ private final Resource test;\r
+ private final STSSuite parent;\r
+ private final String definition;\r
+ private final String name;\r
+ private boolean executed = false;\r
+ private long duration;\r
+ private boolean failed = false;\r
+ private boolean isRunning = false;\r
+ private List<String> output = new ArrayList<>();\r
+ private CombinedCoverage coverage;\r
+ private int priority;\r
+ \r
+ public STSTest(Resource test, STSSuite parent, String definition, String name, int executionPrioprity) {\r
+ this.test = test;\r
+ this.parent = parent;\r
+ this.definition = definition;\r
+ this.name = name;\r
+ this.priority = executionPrioprity;\r
+ }\r
+ \r
+ public String getName() {\r
+ return name;\r
+ }\r
+ \r
+ public String getLabel() {\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append(name);\r
+ if (executed || failed)\r
+ sb.append(" (").append(duration).append(" ms)");\r
+ return sb.toString();\r
+ }\r
+ \r
+ public String getDefinition() {\r
+ return definition;\r
+ }\r
+\r
+ public STSSuite getParent() {\r
+ return parent;\r
+ }\r
+\r
+ public void execute(CommandSession session) {\r
+ isRunning = true;\r
+ \r
+ TestScriptExecutor executor = new TestScriptExecutor(session, new BufferedReader(new StringReader(definition)), new AbstractSCLReportingHandler() {\r
+ \r
+ @Override\r
+ public void print(String text) {\r
+ appendOutput(text + "\n");\r
+ }\r
+ \r
+ @Override\r
+ public void printCommand(String command) {\r
+ appendOutput("> " + command + "\n");\r
+ }\r
+ \r
+ @Override\r
+ public void printError(String error) {\r
+ appendOutput(error + "\n");\r
+ }\r
+ });\r
+ long start = System.currentTimeMillis();\r
+ try {\r
+ if (parent != null)\r
+ parent.startedCount++;\r
+ executor.execute();\r
+ executed = true;\r
+ } catch (Throwable t) {\r
+ t.printStackTrace();\r
+ if (parent != null)\r
+ parent.failureCount++;\r
+ failed = true;\r
+ } finally {\r
+ isRunning = false;\r
+ long end = System.currentTimeMillis();\r
+ duration = end - start;\r
+ }\r
+\r
+ }\r
+\r
+ protected void appendOutput(String text) {\r
+ output.add(text);\r
+ }\r
+\r
+ public List<String> getOutput() {\r
+ return output;\r
+ }\r
+\r
+ public void setCoverage(CombinedCoverage coverage) {\r
+ this.coverage = coverage;\r
+ }\r
+ \r
+ public CombinedCoverage getCoverage() {\r
+ return coverage;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return name + " [priority=" + priority + ", executed=" + executed + ", duration=" + duration + "]";\r
+ }\r
+ }\r
+\r
+ static class STSSuite {\r
+ \r
+ private List<Pattern> moduleNameFilterPatterns = new ArrayList<>();\r
+ private final Resource suite;\r
+ private final String name;\r
+ private STSTest[] children;\r
+ private int startedCount;\r
+ private int errorCount;\r
+ private int failureCount;\r
+ private CoverageBuilder coverageBuilder;\r
+ \r
+ public STSSuite(Resource suite, String name, String moduleNameFilter) {\r
+ this.suite = suite;\r
+ this.name = name;\r
+ for (String s : moduleNameFilter.split(",")) {\r
+ try {\r
+ s = s.trim().replaceAll("\\*", "\\\\w*").toLowerCase();\r
+ moduleNameFilterPatterns.add(Pattern.compile(s));\r
+ } catch (PatternSyntaxException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+\r
+ public void children(STSTest[] children) {\r
+ this.children = children;\r
+ }\r
+\r
+ public STSTest[] getChildren() {\r
+ return children;\r
+ }\r
+\r
+ public String getName() {\r
+ return name;\r
+ }\r
+\r
+ public String getLabel() {\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append(name);\r
+ long totalTime = 0; \r
+ if (children != null) {\r
+ for (STSTest test : children) {\r
+ if (test.executed || test.failed) {\r
+ totalTime += test.duration;\r
+ }\r
+ }\r
+ }\r
+ if (totalTime != 0)\r
+ sb.append(" (").append(totalTime).append(" ms)");\r
+ return sb.toString();\r
+ }\r
+\r
+ public boolean isRunning() {\r
+ boolean running = false;\r
+ if (children != null) {\r
+ for (STSTest test: children) {\r
+ if (test.isRunning) {\r
+ running = true;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ return running;\r
+ }\r
+\r
+ public boolean executed() {\r
+ boolean executed = true;\r
+ if (children != null) {\r
+ for (STSTest test: children) {\r
+ if (!test.executed) {\r
+ executed = false;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ return executed;\r
+ }\r
+\r
+ public boolean failed() {\r
+ boolean failed = false;\r
+ if (children != null) {\r
+ for (STSTest test: children) {\r
+ if (test.failed) {\r
+ failed = true;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ return failed;\r
+ }\r
+ \r
+ public void addCoverage(List<Module> modules) {\r
+ if (coverageBuilder == null) {\r
+ coverageBuilder = new CoverageBuilder();\r
+ }\r
+ for (Module module : modules)\r
+ coverageBuilder.addCoverage(module, true);\r
+ }\r
+\r
+ public CombinedCoverage getCoverage() {\r
+ if (coverageBuilder == null)\r
+ return null;\r
+ return coverageBuilder.getCoverage();\r
+ }\r
+ }\r
+\r
+ \r
+ private STSSuite suite;\r
+ private STSTest test;\r
+ private final List<STSExecutionListener> listeners = new ArrayList<>();\r
+ \r
+ public STSTestSuiteModel() {\r
+ }\r
+ \r
+ public void addListener(STSExecutionListener listener) {\r
+ listeners.add(listener);\r
+ }\r
+ \r
+ public void removeListener(STSExecutionListener listener) {\r
+ listeners.remove(listener);\r
+ }\r
+\r
+ public Object[] getElements() {\r
+ if (suite != null)\r
+ return new Object[] {suite};\r
+ else if (test != null)\r
+ return new Object[] {test};\r
+ else return null;\r
+ }\r
+\r
+ public void execute() {\r
+ \r
+ ModuleRepository repo = new ModuleRepository(SCLOsgi.SOURCE_REPOSITORY);\r
+ if (suite != null) {\r
+ repo.setAdvisor(new ModuleCompilationOptionsAdvisor() {\r
+ \r
+ @Override\r
+ public ModuleCompilationOptions getOptions(String moduleName) {\r
+ boolean coverage = false;\r
+ for (Pattern p : suite.moduleNameFilterPatterns) {\r
+ if (p.matcher(moduleName.toLowerCase()).find()) {\r
+ coverage = true;\r
+ break;\r
+ }\r
+ }\r
+ return new ModuleCompilationOptions(coverage);\r
+ }\r
+ });\r
+ }\r
+ CommandSession session = new CommandSession(repo, null);\r
+ if (suite != null) {\r
+ executeSuite(session);\r
+ } else if (test != null) {\r
+ executeTest(session);\r
+ }\r
+ }\r
+ \r
+ private void testExecuted() {\r
+ listeners.forEach(listener -> {\r
+ listener.testExecuted();\r
+ });\r
+ }\r
+ \r
+ private void executeSuite(CommandSession session) {\r
+ \r
+ for (STSTest test : suite.getChildren()) {\r
+ test.execute(session);\r
+ \r
+ Collection<RuntimeModule> runtimeModules = session.getRuntimeEnvironment().getRuntimeModules();\r
+ List<Module> modules = new ArrayList<>(runtimeModules.size());\r
+ for (RuntimeModule module : runtimeModules) {\r
+ for (Pattern p : suite.moduleNameFilterPatterns) {\r
+ if (p.matcher(module.getModule().getName().toLowerCase()).find()) {\r
+ modules.add(module.getModule());\r
+ }\r
+ }\r
+ }\r
+ test.setCoverage(CoverageUtils.getCoverage(modules));\r
+ suite.addCoverage(modules);\r
+ \r
+ CoverageUtils.resetCoverage(modules);\r
+ \r
+ testExecuted();\r
+ }\r
+\r
+ }\r
+ \r
+ private void executeTest(CommandSession session) {\r
+ \r
+ test.execute(session);\r
+ testExecuted();\r
+ \r
+ Collection<RuntimeModule> runtimeModules = session.getRuntimeEnvironment().getRuntimeModules();\r
+ List<Module> modules = new ArrayList<>(runtimeModules.size());\r
+ for (RuntimeModule module : runtimeModules) {\r
+ modules.add(module.getModule());\r
+ }\r
+ test.setCoverage(CoverageUtils.getCoverage(modules));\r
+ \r
+ CoverageUtils.resetCoverage(modules);\r
+\r
+ }\r
+ \r
+\r
+ public boolean hasChildren(Object element) {\r
+ if (element instanceof STSTest) {\r
+ return false;\r
+ } else if (element instanceof STSSuite) {\r
+ STSSuite suite = (STSSuite) element;\r
+ return (suite.getChildren() != null ? suite.getChildren().length > 0 : false);\r
+ } else {\r
+ throw new IllegalArgumentException(element.toString());\r
+ }\r
+ }\r
+\r
+ public Object getParent(Object element) {\r
+ if (element instanceof STSTest) {\r
+ return ((STSTest) element).getParent();\r
+ } else if (element instanceof STSSuite) {\r
+ return null;\r
+ } else {\r
+ throw new IllegalArgumentException(element.toString());\r
+ }\r
+ }\r
+\r
+ public Object[] getChildren(Object parentElement) {\r
+ if (parentElement instanceof STSTest) {\r
+ return null;\r
+ } else if (parentElement instanceof STSSuite) {\r
+ STSSuite suite = (STSSuite) parentElement;\r
+ return suite.getChildren();\r
+ } else {\r
+ throw new IllegalArgumentException(parentElement.toString());\r
+ }\r
+ }\r
+\r
+ public String getText(Object element) {\r
+ if (element instanceof STSTest)\r
+ return ((STSTest)element).getLabel();\r
+ else if (element instanceof STSSuite)\r
+ return ((STSSuite)element).getLabel();\r
+ else\r
+ throw new IllegalArgumentException(element.toString());\r
+ }\r
+\r
+ public Image getImage(Object element) {\r
+ if (element instanceof STSSuite) {\r
+ STSSuite suite = (STSSuite) element;\r
+ if (suite.isRunning())\r
+ return STSTestSuiteProvider.suiteRunningIcon;\r
+ else if (suite.executed())\r
+ return STSTestSuiteProvider.suiteOkIcon;\r
+ else if (suite.failed())\r
+ return STSTestSuiteProvider.suiteFailIcon;\r
+ else\r
+ return STSTestSuiteProvider.suiteIcon;\r
+ } else if (element instanceof STSTest) {\r
+ STSTest test = (STSTest) element;\r
+ if (test.isRunning)\r
+ return STSTestSuiteProvider.testRunningIcon;\r
+ else if (test.executed)\r
+ return STSTestSuiteProvider.testOkIcon;\r
+ else if (test.failed)\r
+ return STSTestSuiteProvider.testFailIcon;\r
+ else\r
+ return STSTestSuiteProvider.testIcon;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public void updateInput(Resource root) {\r
+ suite = null;\r
+ test = null;\r
+ try {\r
+ Simantics.getSession().syncRequest(new ReadRequest() {\r
+ \r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ Layer0 L0 = Layer0.getInstance(graph);\r
+ TestsResource TESTS = TestsResource.getInstance(graph);\r
+ if (graph.isInstanceOf(root, TESTS.STSTest)) {\r
+ String testName = graph.getRelatedValue2(root, L0.HasName, Bindings.STRING);\r
+ String definition = graph.getRelatedValue2(root, TESTS.STSTest_definition, Bindings.STRING);\r
+ Integer executionPrioprity = graph.getRelatedValue2(root, TESTS.STSTest_executionPriority, Bindings.INTEGER);\r
+ test = new STSTest(root, null, definition, testName, executionPrioprity);\r
+ } else if (graph.isInstanceOf(root, TESTS.STSSuite)) {\r
+ String suiteName = graph.getRelatedValue2(root, L0.HasName, Bindings.STRING);\r
+ String moduleNameFilter = graph.getPossibleRelatedValue2(root, TESTS.STSSuite_moduleNameFilter, Bindings.STRING);\r
+ suite = new STSSuite(root, suiteName, moduleNameFilter);\r
+ List<STSTest> tests = new ArrayList<>();\r
+ for (Resource test : graph.getObjects(root, L0.ConsistsOf)) {\r
+ String testName = graph.getRelatedValue2(test, L0.HasName, Bindings.STRING);\r
+ String definition = graph.getRelatedValue2(test, TESTS.STSTest_definition, Bindings.STRING);\r
+ Integer executionPrioprity = graph.getRelatedValue2(test, TESTS.STSTest_executionPriority, Bindings.INTEGER);\r
+ tests.add(new STSTest(test, suite, definition, testName, executionPrioprity));\r
+ }\r
+ Collections.sort(tests, (o1, o2) -> {\r
+ if (o1.priority < o2.priority)\r
+ return -1;\r
+ if (o1.priority > o2.priority)\r
+ return 1;\r
+ return 0;\r
+ });\r
+ suite.children(tests.toArray(new STSTest[tests.size()]));\r
+ } else {\r
+ throw new IllegalArgumentException(root.toString());\r
+ }\r
+ }\r
+ });\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ public List<String> getOutput(Object element) {\r
+ if (element instanceof STSTest) {\r
+ STSTest test = (STSTest) element;\r
+ return test.getOutput();\r
+ }\r
+ return Collections.emptyList();\r
+ }\r
+\r
+ public int getStartedCount() {\r
+ if (suite != null)\r
+ return suite.startedCount;\r
+ else\r
+ return 0;\r
+ }\r
+\r
+ public int getIgnoredCount() {\r
+ return 0;\r
+ }\r
+\r
+ public int getTotalCount() {\r
+ if (suite != null && suite.getChildren() != null)\r
+ return suite.getChildren().length;\r
+ else if (test != null)\r
+ return 1;\r
+ else\r
+ return 0;\r
+ }\r
+\r
+ public int getErrorCount() {\r
+ if (suite != null)\r
+ return suite.errorCount;\r
+ return 0;\r
+ }\r
+\r
+ public int getFailureCount() {\r
+ if (suite != null)\r
+ return suite.failureCount;\r
+ return 0;\r
+ }\r
+\r
+ public int getAssumptionFailureCount() {\r
+ return 0;\r
+ }\r
+\r
+ public boolean isStopped() {\r
+ if (suite != null)\r
+ return !suite.isRunning();\r
+ else\r
+ return test.isRunning;\r
+ }\r
+}\r
+\r