569f6fbdc7a6d8df1d11fb63876624cf79f97175
[simantics/platform.git] / bundles / org.simantics.tests.modelled.ui / src / org / simantics / tests / modelled / ui / STSTestSuiteModel.java
1 package org.simantics.tests.modelled.ui;
2
3 import java.io.BufferedReader;
4 import java.io.StringReader;
5 import java.util.ArrayList;
6 import java.util.Collection;
7 import java.util.Collections;
8 import java.util.List;
9 import java.util.regex.Pattern;
10 import java.util.regex.PatternSyntaxException;
11
12 import org.eclipse.swt.graphics.Image;
13 import org.simantics.Simantics;
14 import org.simantics.databoard.Bindings;
15 import org.simantics.db.ReadGraph;
16 import org.simantics.db.Resource;
17 import org.simantics.db.common.request.ReadRequest;
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.layer0.Layer0;
20 import org.simantics.scl.compiler.commands.CommandSession;
21 import org.simantics.scl.compiler.commands.TestScriptExecutor;
22 import org.simantics.scl.compiler.module.Module;
23 import org.simantics.scl.compiler.module.coverage.CombinedCoverage;
24 import org.simantics.scl.compiler.module.coverage.CoverageBuilder;
25 import org.simantics.scl.compiler.module.coverage.CoverageUtils;
26 import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
27 import org.simantics.scl.compiler.module.options.ModuleCompilationOptionsAdvisor;
28 import org.simantics.scl.compiler.module.repository.ModuleRepository;
29 import org.simantics.scl.compiler.runtime.RuntimeModule;
30 import org.simantics.scl.osgi.SCLOsgi;
31 import org.simantics.scl.runtime.reporting.AbstractSCLReportingHandler;
32 import org.simantics.tests.modelled.ontology.TestsResource;
33 import org.simantics.utils.strings.AlphanumComparator;
34
35 public class STSTestSuiteModel {
36
37     static class STSTest {
38         
39         private final Resource test;
40         private final STSSuite parent;
41         private final String definition;
42         private final String name;
43         private boolean executed = false;
44         private long duration;
45         private boolean failed = false;
46         private boolean isRunning = false;
47         private List<String> output = new ArrayList<>();
48         private CombinedCoverage coverage;
49         private int priority;
50         
51         public STSTest(Resource test, STSSuite parent, String definition, String name, int executionPrioprity) {
52             this.test = test;
53             this.parent = parent;
54             this.definition = definition;
55             this.name = name;
56             this.priority = executionPrioprity;
57         }
58         
59         public String getName() {
60             return name;
61         }
62         
63         public String getLabel() {
64             StringBuilder sb = new StringBuilder();
65             sb.append(name);
66             if (executed || failed)
67                 sb.append(" (").append(duration).append(" ms)");
68             return sb.toString();
69         }
70         
71         public String getDefinition() {
72             return definition;
73         }
74
75         public STSSuite getParent() {
76             return parent;
77         }
78
79         public void execute(CommandSession session) {
80             isRunning = true;
81             
82             TestScriptExecutor executor = new TestScriptExecutor(session, new BufferedReader(new StringReader(definition)), new AbstractSCLReportingHandler() {
83                 
84                 @Override
85                 public void print(String text) {
86                     appendOutput(text + "\n");
87                 }
88                 
89                 @Override
90                 public void printCommand(String command) {
91                     appendOutput("> " + command + "\n");
92                 }
93                 
94                 @Override
95                 public void printError(String error) {
96                     appendOutput(error + "\n");
97                 }
98             });
99             long start = System.currentTimeMillis();
100             try {
101                 if (parent != null)
102                     parent.startedCount++;
103                 executor.execute();
104                 executed = true;
105             } catch (Throwable t) {
106                 t.printStackTrace();
107                 if (parent != null)
108                     parent.failureCount++;
109                 failed = true;
110             } finally {
111                 isRunning = false;
112                 long end = System.currentTimeMillis();
113                 duration = end - start;
114             }
115
116         }
117
118         protected void appendOutput(String text) {
119             output.add(text);
120         }
121
122         public List<String> getOutput() {
123             return output;
124         }
125
126         public void setCoverage(CombinedCoverage coverage) {
127             this.coverage = coverage;
128         }
129         
130         public CombinedCoverage getCoverage() {
131             return coverage;
132         }
133         
134         @Override
135         public String toString() {
136             return name + " [priority=" + priority + ", executed=" + executed + ", duration=" + duration + "]";
137         }
138     }
139
140     static class STSSuite {
141         
142         private List<Pattern> moduleNameFilterPatterns = new ArrayList<>();
143         private final Resource suite;
144         private final String name;
145         private STSTest[] children;
146         private int startedCount;
147         private int errorCount;
148         private int failureCount;
149         private CoverageBuilder coverageBuilder;
150         
151         public STSSuite(Resource suite, String name, String moduleNameFilter) {
152             this.suite = suite;
153             this.name = name;
154             for (String s : moduleNameFilter.split(",")) {
155                 try {
156                     s = s.trim().replaceAll("\\*", "\\\\w*").toLowerCase();
157                     moduleNameFilterPatterns.add(Pattern.compile(s));
158                 } catch (PatternSyntaxException e) {
159                     e.printStackTrace();
160                 }
161             }
162         }
163
164         public void children(STSTest[] children) {
165             this.children = children;
166         }
167
168         public STSTest[] getChildren() {
169             return children;
170         }
171
172         public String getName() {
173             return name;
174         }
175
176         public String getLabel() {
177             StringBuilder sb = new StringBuilder();
178             sb.append(name);
179             long totalTime = 0; 
180             if (children != null) {
181                 for (STSTest test : children) {
182                     if (test.executed || test.failed) {
183                         totalTime += test.duration;
184                     }
185                 }
186             }
187             if (totalTime != 0)
188                 sb.append(" (").append(totalTime).append(" ms)");
189             return sb.toString();
190         }
191
192         public boolean isRunning() {
193             boolean running = false;
194             if (children != null) {
195                 for (STSTest test: children) {
196                     if (test.isRunning) {
197                         running = true;
198                         break;
199                     }
200                 }
201             }
202             return running;
203         }
204
205         public boolean executed() {
206             boolean executed = true;
207             if (children != null) {
208                 for (STSTest test: children) {
209                     if (!test.executed) {
210                         executed = false;
211                         break;
212                     }
213                 }
214             }
215             return executed;
216         }
217
218         public boolean failed() {
219             boolean failed = false;
220             if (children != null) {
221                 for (STSTest test: children) {
222                     if (test.failed) {
223                         failed = true;
224                         break;
225                     }
226                 }
227             }
228             return failed;
229         }
230         
231         public void addCoverage(List<Module> modules) {
232             if (coverageBuilder == null) {
233                 coverageBuilder = new CoverageBuilder();
234             }
235             for (Module module : modules)
236                 coverageBuilder.addCoverage(module, true);
237         }
238
239         public CombinedCoverage getCoverage() {
240             if (coverageBuilder == null)
241                 return null;
242             return coverageBuilder.getCoverage();
243         }
244     }
245
246     
247     private STSSuite suite;
248     private STSTest test;
249     private final List<STSExecutionListener> listeners = new ArrayList<>();
250     
251     public STSTestSuiteModel() {
252     }
253     
254     public void addListener(STSExecutionListener listener) {
255         listeners.add(listener);
256     }
257     
258     public void removeListener(STSExecutionListener listener) {
259         listeners.remove(listener);
260     }
261
262     public Object[] getElements() {
263         if (suite != null)
264             return new Object[] {suite};
265         else if (test != null)
266             return new Object[] {test};
267         else return null;
268     }
269
270     public void execute() {
271         
272         ModuleRepository repo = new ModuleRepository(SCLOsgi.SOURCE_REPOSITORY);
273         if (suite != null) {
274             repo.setAdvisor(new ModuleCompilationOptionsAdvisor() {
275                 
276                 @Override
277                 public ModuleCompilationOptions getOptions(String moduleName) {
278                     boolean coverage = false;
279                     for (Pattern p : suite.moduleNameFilterPatterns) {
280                         if (p.matcher(moduleName.toLowerCase()).find()) {
281                             coverage = true;
282                             break;
283                         }
284                     }
285                     return new ModuleCompilationOptions(coverage);
286                 }
287             });
288         }
289         CommandSession session = new CommandSession(repo, null);
290         if (suite != null) {
291             executeSuite(session);
292         } else if (test != null) {
293             executeTest(session);
294         }
295     }
296     
297     private void testExecuted() {
298         listeners.forEach(listener -> {
299             listener.testExecuted();
300         });
301     }
302     
303     private void executeSuite(CommandSession session) {
304         
305         for (STSTest test : suite.getChildren()) {
306             test.execute(session);
307             
308             Collection<RuntimeModule> runtimeModules = session.getRuntimeEnvironment().getRuntimeModules();
309             List<Module> modules = new ArrayList<>(runtimeModules.size());
310             for (RuntimeModule module : runtimeModules) {
311                 for (Pattern p : suite.moduleNameFilterPatterns) {
312                     if (p.matcher(module.getModule().getName().toLowerCase()).find()) {
313                         modules.add(module.getModule());
314                     }
315                 }
316             }
317             test.setCoverage(CoverageUtils.getCoverage(modules));
318             suite.addCoverage(modules);
319             
320             CoverageUtils.resetCoverage(modules);
321             
322             testExecuted();
323         }
324
325     }
326     
327     private void executeTest(CommandSession session) {
328         
329         test.execute(session);
330         testExecuted();
331         
332         Collection<RuntimeModule> runtimeModules = session.getRuntimeEnvironment().getRuntimeModules();
333         List<Module> modules = new ArrayList<>(runtimeModules.size());
334         for (RuntimeModule module : runtimeModules) {
335             modules.add(module.getModule());
336         }
337         test.setCoverage(CoverageUtils.getCoverage(modules));
338         
339         CoverageUtils.resetCoverage(modules);
340
341     }
342     
343
344     public boolean hasChildren(Object element) {
345         if (element instanceof STSTest) {
346             return false;
347         } else if (element instanceof STSSuite) {
348             STSSuite suite = (STSSuite) element;
349             return (suite.getChildren() != null ? suite.getChildren().length > 0 : false);
350         } else {
351             throw new IllegalArgumentException(element.toString());
352         }
353     }
354
355     public Object getParent(Object element) {
356         if (element instanceof STSTest) {
357             return ((STSTest) element).getParent();
358         } else if (element instanceof STSSuite) {
359             return null;
360         } else {
361             throw new IllegalArgumentException(element.toString());
362         }
363     }
364
365     public Object[] getChildren(Object parentElement) {
366         if (parentElement instanceof STSTest) {
367             return null;
368         } else if (parentElement instanceof STSSuite) {
369             STSSuite suite = (STSSuite) parentElement;
370             return suite.getChildren();
371         } else {
372             throw new IllegalArgumentException(parentElement.toString());
373         }
374     }
375
376     public String getText(Object element) {
377         if (element instanceof STSTest)
378             return ((STSTest)element).getLabel();
379         else if (element instanceof STSSuite)
380             return ((STSSuite)element).getLabel();
381         else
382             throw new IllegalArgumentException(element.toString());
383     }
384
385     public Image getImage(Object element) {
386         if (element instanceof STSSuite) {
387             STSSuite suite = (STSSuite) element;
388             if (suite.isRunning())
389                 return STSTestSuiteProvider.suiteRunningIcon;
390             else if (suite.executed())
391                 return STSTestSuiteProvider.suiteOkIcon;
392             else if (suite.failed())
393                 return STSTestSuiteProvider.suiteFailIcon;
394             else
395                 return STSTestSuiteProvider.suiteIcon;
396         } else if (element instanceof STSTest) {
397             STSTest test = (STSTest) element;
398             if (test.isRunning)
399                 return STSTestSuiteProvider.testRunningIcon;
400             else if (test.executed)
401                 return STSTestSuiteProvider.testOkIcon;
402             else if (test.failed)
403                 return STSTestSuiteProvider.testFailIcon;
404             else
405                 return STSTestSuiteProvider.testIcon;
406         }
407         return null;
408     }
409
410     public void updateInput(Resource root) {
411         suite = null;
412         test = null;
413         try {
414             Simantics.getSession().syncRequest(new ReadRequest() {
415                 
416                 @Override
417                 public void run(ReadGraph graph) throws DatabaseException {
418                     Layer0 L0 = Layer0.getInstance(graph);
419                     TestsResource TESTS = TestsResource.getInstance(graph);
420                     if (graph.isInstanceOf(root, TESTS.STSTest)) {
421                         String testName = graph.getRelatedValue2(root, L0.HasName, Bindings.STRING);
422                         String definition = graph.getRelatedValue2(root, TESTS.STSTest_definition, Bindings.STRING);
423                         Integer executionPrioprity = graph.getRelatedValue2(root, TESTS.STSTest_executionPriority, Bindings.INTEGER);
424                         test = new STSTest(root, null, definition, testName, executionPrioprity);
425                     } else if (graph.isInstanceOf(root, TESTS.STSSuite)) {
426                         String suiteName = graph.getRelatedValue2(root, L0.HasName, Bindings.STRING);
427                         String moduleNameFilter = graph.getPossibleRelatedValue2(root, TESTS.STSSuite_moduleNameFilter, Bindings.STRING);
428                         suite = new STSSuite(root, suiteName, moduleNameFilter);
429                         List<STSTest> tests = new ArrayList<>();
430                         for (Resource test : graph.getObjects(root, L0.ConsistsOf)) {
431                             String testName = graph.getRelatedValue2(test, L0.HasName, Bindings.STRING);
432                             String definition = graph.getRelatedValue2(test, TESTS.STSTest_definition, Bindings.STRING);
433                             Integer executionPrioprity = graph.getRelatedValue2(test, TESTS.STSTest_executionPriority, Bindings.INTEGER);
434                             tests.add(new STSTest(test, suite, definition, testName, executionPrioprity));
435                         }
436                         Collections.sort(tests, (o1, o2) -> {
437                             if (o1.priority < o2.priority)
438                                 return -1;
439                             else if (o1.priority > o2.priority)
440                                 return 1;
441                             else return AlphanumComparator.COMPARATOR.compare(o1.name, o2.name);
442                         });
443                         suite.children(tests.toArray(new STSTest[tests.size()]));
444                     } else {
445                         throw new IllegalArgumentException(root.toString());
446                     }
447                 }
448             });
449         } catch (DatabaseException e) {
450             e.printStackTrace();
451         }
452     }
453
454     public List<String> getOutput(Object element) {
455         if (element instanceof STSTest) {
456             STSTest test = (STSTest) element;
457             return test.getOutput();
458         }
459         return Collections.emptyList();
460     }
461
462     public int getStartedCount() {
463         if (suite != null)
464             return suite.startedCount;
465         else
466             return 0;
467     }
468
469     public int getIgnoredCount() {
470         return 0;
471     }
472
473     public int getTotalCount() {
474         if (suite != null && suite.getChildren() != null)
475             return suite.getChildren().length;
476         else if (test != null)
477             return 1;
478         else
479             return 0;
480     }
481
482     public int getErrorCount() {
483         if (suite != null)
484             return suite.errorCount;
485         return 0;
486     }
487
488     public int getFailureCount() {
489         if (suite != null)
490             return suite.failureCount;
491         return 0;
492     }
493
494     public int getAssumptionFailureCount() {
495         return 0;
496     }
497
498     public boolean isStopped() {
499         if (suite != null)
500             return !suite.isRunning();
501         else
502             return test.isRunning;
503     }
504 }
505