203f2832501c57d98aa48bd54e344c833fb373d3
[simantics/platform.git] / bundles / org.simantics.tests.modelled.ui / src / org / simantics / tests / modelled / ui / STSTestRunnerView.java
1 package org.simantics.tests.modelled.ui;
2
3 import java.util.List;
4 import java.util.concurrent.Executors;
5
6 import javax.annotation.PostConstruct;
7 import javax.annotation.PreDestroy;
8
9 import org.eclipse.e4.ui.di.Focus;
10 import org.eclipse.jface.layout.TreeColumnLayout;
11 import org.eclipse.jface.viewers.CellLabelProvider;
12 import org.eclipse.jface.viewers.ColumnWeightData;
13 import org.eclipse.jface.viewers.ISelection;
14 import org.eclipse.jface.viewers.ISelectionChangedListener;
15 import org.eclipse.jface.viewers.OwnerDrawLabelProvider;
16 import org.eclipse.jface.viewers.SelectionChangedEvent;
17 import org.eclipse.jface.viewers.TreeSelection;
18 import org.eclipse.jface.viewers.TreeViewer;
19 import org.eclipse.jface.viewers.TreeViewerColumn;
20 import org.eclipse.jface.viewers.ViewerCell;
21 import org.eclipse.swt.SWT;
22 import org.eclipse.swt.custom.CTabFolder;
23 import org.eclipse.swt.custom.CTabItem;
24 import org.eclipse.swt.custom.SashForm;
25 import org.eclipse.swt.custom.StyledText;
26 import org.eclipse.swt.custom.ViewForm;
27 import org.eclipse.swt.graphics.Point;
28 import org.eclipse.swt.layout.FormAttachment;
29 import org.eclipse.swt.layout.FormData;
30 import org.eclipse.swt.layout.GridData;
31 import org.eclipse.swt.layout.GridLayout;
32 import org.eclipse.swt.widgets.Composite;
33 import org.eclipse.swt.widgets.Event;
34 import org.eclipse.swt.widgets.Layout;
35 import org.eclipse.swt.widgets.Tree;
36 import org.eclipse.swt.widgets.TreeColumn;
37 import org.eclipse.ui.part.PageBook;
38 import org.simantics.db.Resource;
39 import org.simantics.scl.compiler.module.coverage.Coverage;
40
41 public class STSTestRunnerView {
42     
43     public static final String ID = "org.simantics.tests.modelled.ui.stsTestRunnerView";
44
45     private Resource test;
46     private SashForm sashForm;
47     private PageBook viewerbook;
48     private TreeViewer treeViewer;
49 //    private ITreeContentProvider treeContentProvider;
50     private STSTestSuiteProvider provider;
51     private StyledText output;
52     private STSCounterPanel counterPanel;
53     private STSProgressBar progressBar;
54     private Composite counterComposite;
55
56     @PostConstruct
57     void createView(Composite parent) {
58         
59         GridLayout gridLayout= new GridLayout();
60         gridLayout.marginWidth= 0;
61         gridLayout.marginHeight= 0;
62         parent.setLayout(gridLayout);
63         
64         counterComposite= createProgressCountPanel(parent);
65         counterComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
66         counterComposite.pack();
67         
68         SashForm sashForm = createSashForm(parent);
69         sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
70     }
71     
72     private SashForm createSashForm(Composite parent) {
73         sashForm = new SashForm(parent, SWT.VERTICAL);
74
75         ViewForm top = new ViewForm(sashForm, SWT.NONE);
76
77         Composite empty = new Composite(top, SWT.NONE);
78         empty.setLayout(new Layout() {
79             @Override
80             protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
81                 return new Point(1, 1); // (0, 0) does not work with super-intelligent ViewForm
82             }
83             @Override
84             protected void layout(Composite composite, boolean flushCache) {
85             }
86         });
87         top.setTopLeft(empty); // makes ViewForm draw the horizontal separator line ...
88 //        fTestViewer= new TestViewer(top, fClipboard, this);
89         createTestViewers(top);
90         top.setContent(viewerbook);
91         treeViewer.setInput(test);
92
93         ViewForm bottom = new ViewForm(sashForm, SWT.NONE);
94
95         CTabFolder folder = new CTabFolder(bottom, SWT.BORDER);
96         folder.setLayoutData(new GridData(GridData.FILL_BOTH));
97         
98         CTabItem item1 = new CTabItem(folder, SWT.NONE);
99         item1.setText("Execution");
100 //        PageBook fViewerbook2= new PageBook(bottom, SWT.NULL);
101         // Upper
102         output = new StyledText(folder, SWT.MULTI | SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL);
103 //        output.setFont(textFont);
104         {
105             FormData formData = new FormData();
106             formData.top = new FormAttachment(0);      
107 //            formData.bottom = new FormAttachment(sash);
108             formData.left = new FormAttachment(0);
109             formData.right = new FormAttachment(100);
110             output.setLayoutData(formData);
111         }
112         item1.setControl(output);
113 //        fViewerbook2.showPage(output);
114         bottom.setContent(folder);
115         folder.setSelection(0);
116
117         CTabItem item2 = new CTabItem(folder, SWT.NONE);
118         item2.setText("Coverage");
119         
120         Composite treeComposite = new Composite(folder, SWT.NONE);
121         
122         TreeViewer viewer = createCoverageViewer(treeComposite);
123         item2.setControl(treeComposite);
124         
125         treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
126             
127             @Override
128             public void selectionChanged(SelectionChangedEvent event) {
129                 ISelection selection = event.getSelection();
130                 TreeSelection sel = (TreeSelection) selection;
131                 List<String> testOutput = provider.getModel().getOutput(sel.getFirstElement());
132                 
133                 viewer.setInput(sel.getFirstElement());
134                 
135                 StringBuilder sb = new StringBuilder();
136                 for (String o : testOutput) {
137                     sb.append(o);
138                 }
139                 output.setText(sb.toString());
140             }
141         });
142         
143         sashForm.setWeights(new int[] {50, 50});
144         return sashForm;
145     }
146     
147     protected static final int COLUMN_ELEMENT = 0;
148     protected static final int COLUMN_RATIO = 1;
149     protected static final int COLUMN_COVERED = 2;
150     protected static final int COLUMN_MISSED = 3;
151     protected static final int COLUMN_TOTAL = 4;
152     
153     private TreeViewer createCoverageViewer(Composite parent) {
154         // Composite treeViewerComposite = new Composite(parent, SWT.NONE);
155
156         TreeColumnLayout layout = new TreeColumnLayout();
157         parent.setLayout(layout);
158         
159         Tree tree = new Tree(parent, SWT.MULTI | SWT.FULL_SELECTION);
160         tree.setHeaderVisible(true);
161         tree.setLinesVisible(true);
162         
163         STSCoverageProvider provider = new STSCoverageProvider();
164
165         TreeViewer viewer = new TreeViewer(tree);
166         
167         CoverageViewSorter sorter = new CoverageViewSorter(viewer);
168         
169         final TreeViewerColumn column0 = new TreeViewerColumn(viewer, SWT.LEFT);
170         
171         column0.setLabelProvider(new CellLabelProvider() {
172
173             
174             @Override
175             public void update(ViewerCell cell) {
176                 cell.setText(provider.getText(cell.getElement()));
177                 cell.setImage(provider.getImage(cell.getElement()));
178             }
179         });
180          sorter.addColumn(column0, COLUMN_ELEMENT);
181
182         final TreeViewerColumn column1 = new TreeViewerColumn(viewer, SWT.RIGHT);
183         column1.setLabelProvider(new OwnerDrawLabelProvider() {
184
185             @Override
186             public void update(ViewerCell cell) {
187                 cell.setText(provider.getRatio(cell.getElement()));
188             }
189
190             @Override
191             protected void erase(Event event, Object element) {
192             }
193
194             @Override
195             protected void measure(Event event, Object element) {
196             }
197
198             @Override
199             protected void paint(Event event, Object element) {
200                 final Coverage coverage = (Coverage) element;
201                 if (coverage != null) {
202                     RedGreenBar.draw(event, column1.getColumn().getWidth(), coverage);
203                 }
204             }
205         });
206         sorter.addColumn(column1, COLUMN_RATIO);
207
208         final TreeViewerColumn column2 = new TreeViewerColumn(viewer, SWT.RIGHT);
209         column2.setLabelProvider(new CellLabelProvider() {
210
211             @Override
212             public void update(ViewerCell cell) {
213                 cell.setText(provider.getCovered(cell.getElement()));
214             }
215         });
216         sorter.addColumn(column2, COLUMN_COVERED);
217
218         final TreeViewerColumn column3 = new TreeViewerColumn(viewer, SWT.RIGHT);
219         column3.setLabelProvider(new CellLabelProvider() {
220
221             @Override
222             public void update(ViewerCell cell) {
223                 cell.setText(provider.getMissed(cell.getElement()));
224             }
225         });
226         sorter.addColumn(column3, COLUMN_MISSED);
227
228         final TreeViewerColumn column4 = new TreeViewerColumn(viewer, SWT.RIGHT);
229         column4.setLabelProvider(new CellLabelProvider() {
230
231             @Override
232             public void update(ViewerCell cell) {
233                 cell.setText(provider.getTotal(cell.getElement()));
234             }
235         });
236         sorter.addColumn(column4, COLUMN_TOTAL);
237
238 //        viewer.addFilter(new ViewerFilter() {
239 //            public boolean select(Viewer viewer, Object parentElement, Object element) {
240 //                if (element == LOADING_ELEMENT) {
241 //                    return true;
242 //                } else {
243 //                    final ICoverageNode c = CoverageTools.getCoverageInfo(element);
244 //                    if (c == null) {
245 //                        return false;
246 //                    }
247 //                    final ICounter instructions = c.getInstructionCounter();
248 //                    if (instructions.getTotalCount() == 0) {
249 //                        return false;
250 //                    }
251 //                    if (settings.getHideUnusedElements() && instructions.getCoveredCount() == 0) {
252 //                        return false;
253 //                    }
254 //                    return true;
255 //                }
256 //            }
257 //        });
258         viewer.setComparator(sorter);
259         
260         layout.setColumnData(column0.getColumn(), new ColumnWeightData(0, 50, false));
261         layout.setColumnData(column1.getColumn(), new ColumnWeightData(0, 50, false));
262         layout.setColumnData(column2.getColumn(), new ColumnWeightData(0, 50, false));
263         layout.setColumnData(column3.getColumn(), new ColumnWeightData(0, 50, false));
264         layout.setColumnData(column4.getColumn(), new ColumnWeightData(0, 50, false));
265         
266         String[] columns = new String[] {"Module", "Coverage", "Covered Instructions", "Missed Instructions", "Total Instructions"};
267         TreeColumn[] columns2 = viewer.getTree().getColumns();
268         for (int i = 0; i < columns2.length; i++) {
269             columns2[i].setText(columns[i]);
270         }
271         restoreColumnWidth(viewer);
272         viewer.setContentProvider(provider);
273         return viewer;
274
275 //        viewer.addOpenListener(new IOpenListener() {
276 //            public void open(OpenEvent event) {
277 //                openAction.run((IStructuredSelection) event.getSelection());
278 //            }
279 //        });
280
281 //        MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
282 //        menuMgr.setRemoveAllWhenShown(true);
283 //        tree.setMenu(menuMgr.createContextMenu(tree));
284 //        getSite().registerContextMenu(menuMgr, viewer);
285 //
286 //        CoverageTools.getSessionManager().addSessionListener(descriptionUpdater);
287 //        CoverageTools.addJavaCoverageListener(coverageListener);
288     }
289     
290     private static final int[] DEFAULT_COLUMNWIDTH = new int[] { 200, 100, 120,
291             120, 120 };
292     
293     public void restoreColumnWidth(TreeViewer viewer) {
294         final TreeColumn[] columns = viewer.getTree().getColumns();
295         for (int i = 0; i < DEFAULT_COLUMNWIDTH.length; i++) {
296           columns[i].setWidth(DEFAULT_COLUMNWIDTH[i]);
297         }
298       }
299
300     protected Composite createProgressCountPanel(Composite parent) {
301         Composite composite= new Composite(parent, SWT.NONE);
302         GridLayout layout= new GridLayout();
303         composite.setLayout(layout);
304         layout.numColumns = 1;
305
306         counterPanel = new STSCounterPanel(composite);
307         counterPanel.setLayoutData(
308             new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
309         progressBar = new STSProgressBar(composite);
310         progressBar.setLayoutData(
311                 new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
312         return composite;
313     }
314     
315     private void createTestViewers(Composite parent) {
316         viewerbook = new PageBook(parent, SWT.NULL);
317
318         treeViewer = new TreeViewer(viewerbook, SWT.V_SCROLL | SWT.SINGLE);
319         treeViewer.setUseHashlookup(true);
320         
321         STSTestSuiteModel model = new STSTestSuiteModel();
322         model.addListener(new STSExecutionListener() {
323             
324             @Override
325             public void testExecuted() {
326                 treeViewer.getControl().getDisplay().syncExec(() -> {
327                     refreshCounters();
328                     treeViewer.refresh();
329                 });
330             }
331         });
332         
333         provider = new STSTestSuiteProvider(model);
334         
335         treeViewer.setContentProvider(provider);
336         treeViewer.setLabelProvider(provider);
337
338
339         viewerbook.showPage(treeViewer.getTree());
340         
341     }
342     
343
344     @Focus
345     void setFocus() {
346         sashForm.setFocus();
347     }
348
349     public void currentTest(Resource test) {
350         treeViewer.setInput(test);
351         refreshCounters();
352     }
353     
354     private void refreshCounters() {
355         // TODO: Inefficient. Either
356        // - keep a boolean fHasTestRun and update only on changes, or
357        // - improve components to only redraw on changes (once!).
358
359        int startedCount;
360        int ignoredCount;
361        int totalCount;
362        int errorCount;
363        int failureCount;
364        int assumptionFailureCount;
365        boolean hasErrorsOrFailures;
366        boolean stopped;
367
368        STSTestSuiteModel model = provider.getModel();
369        if (model != null) {
370            startedCount= model.getStartedCount();
371            ignoredCount= model.getIgnoredCount();
372            totalCount= model.getTotalCount();
373            errorCount= model.getErrorCount();
374            failureCount= model.getFailureCount();
375            assumptionFailureCount = model.getAssumptionFailureCount();
376            hasErrorsOrFailures= errorCount + failureCount > 0;
377            stopped= model.isStopped();
378        } else {
379            startedCount= 0;
380            ignoredCount= 0;
381            totalCount= 0;
382            errorCount= 0;
383            failureCount= 0;
384            assumptionFailureCount = 0;
385            hasErrorsOrFailures= false;
386            stopped= false;
387        }
388
389        counterPanel.setTotal(totalCount);
390        counterPanel.setRunValue(startedCount, ignoredCount, assumptionFailureCount);
391        counterPanel.setErrorValue(errorCount);
392        counterPanel.setFailureValue(failureCount);
393
394        int ticksDone;
395        if (startedCount == 0)
396            ticksDone= 0;
397        else if (startedCount == totalCount &&  model.isStopped())
398            ticksDone= totalCount;
399        else
400            ticksDone= startedCount - 1;
401
402        progressBar.reset(hasErrorsOrFailures, stopped, ticksDone, totalCount);
403    }
404
405     public void execute() {
406         Executors.newSingleThreadExecutor().submit(new Runnable() {
407
408             @Override
409             public void run() {
410                 provider.getModel().execute();
411             }
412         });
413     }
414     
415     @PreDestroy
416     public void destroy() {
417         provider.dispose();
418     }
419 }