1 package eu.simuline.testhelpers;
2
3 import eu.simuline.util.images.GifResource;
4
5 import java.awt.event.ActionEvent;
6 import java.awt.event.KeyEvent;
7
8 import javax.swing.AbstractAction;
9 import javax.swing.KeyStroke;
10 import javax.swing.SwingUtilities;
11
12 import org.junit.runner.JUnitCore;
13 import org.junit.runner.Request;
14 import org.junit.runner.Runner;
15 import org.junit.runner.Result;
16 import org.junit.runner.Description;
17
18 import org.junit.runner.manipulation.Filter;
19
20 import org.junit.runner.notification.RunListener;
21 import org.junit.runner.notification.RunNotifier;
22 import org.junit.runner.notification.StoppedByUserException;
23
24 import org.javalobby.icons20x20.Open;
25 import org.javalobby.icons20x20.ExecuteProject;
26 import org.javalobby.icons20x20.Stop;
27 import org.javalobby.icons20x20.Hammer;
28 import org.javalobby.icons20x20.Delete;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public final class Actions {
49
50
51
52
53
54
55
56
57
58 class OpenAction extends AbstractAction {
59
60 private static final long serialVersionUID = -589L;
61
62 OpenAction() {
63 super("Open", GifResource.getIcon(Open.class));
64 putValue(SHORT_DESCRIPTION, "Opens a class and executes run. ");
65 putValue(MNEMONIC_KEY, KeyEvent.VK_O);
66 putValue(ACCELERATOR_KEY,
67 KeyStroke.getKeyStroke(KeyEvent.VK_O,
68 ActionEvent.CTRL_MASK));
69 }
70
71 public void actionPerformed(ActionEvent event) {
72 String clsName = Actions.this.guiRunner.openClassChooser();
73
74 if (clsName == null) {
75
76 System.out.println("Warning: no class choosen");
77 return;
78 }
79 assert clsName != null;
80 System.out.println("Info: class `" + clsName + "' choosen");
81 Actions.this.coreRunner = new CoreRunner(clsName);
82
83
84 Actions.this.filter = null;
85 Actions.this.getStartAction().actionPerformed(null);
86 }
87 }
88
89
90
91
92
93 class StartAction extends AbstractAction {
94
95 private static final long serialVersionUID = -589L;
96
97 StartAction() {
98 super("Run", GifResource.getIcon(ExecuteProject.class));
99 putValue(SHORT_DESCRIPTION, "Runs the testcases. ");
100 putValue(MNEMONIC_KEY, KeyEvent.VK_R);
101 putValue(ACCELERATOR_KEY,
102 KeyStroke.getKeyStroke(KeyEvent.VK_R,
103 ActionEvent.CTRL_MASK));
104 }
105
106 public void actionPerformed(ActionEvent event) {
107 Actions.this.coreRunner = new CoreRunner(Actions.this.coreRunner);
108 Actions.this.coreRunner.start();
109 }
110 }
111
112
113
114
115
116 class StopAction extends AbstractAction {
117
118 private static final long serialVersionUID = -589L;
119
120 StopAction() {
121 super("Stop", GifResource.getIcon(Stop.class));
122 putValue(SHORT_DESCRIPTION,
123 "Stops after having executed the current testcase. ");
124 putValue(MNEMONIC_KEY, KeyEvent.VK_S);
125 putValue(ACCELERATOR_KEY,
126 KeyStroke.getKeyStroke(KeyEvent.VK_S,
127 ActionEvent.CTRL_MASK));
128 }
129
130 public void actionPerformed(ActionEvent event) {
131 Actions.this.coreRunner.pleaseStop();
132 }
133 }
134
135
136
137
138
139
140
141 class BreakAction extends AbstractAction {
142
143 private static final long serialVersionUID = -589L;
144
145 BreakAction() {
146 super("Break", GifResource.getIcon(Hammer.class));
147 putValue(SHORT_DESCRIPTION,
148 "Tries to break execution of current testcases. ");
149 putValue(MNEMONIC_KEY, KeyEvent.VK_B);
150 putValue(ACCELERATOR_KEY,
151 KeyStroke.getKeyStroke(KeyEvent.VK_B,
152 ActionEvent.CTRL_MASK));
153 }
154
155 @SuppressWarnings("deprecation")
156 public void actionPerformed(ActionEvent event) {
157
158 System.out.println("Break...");
159 Actions.this.coreRunner.pleaseStop();
160
161
162 Actions.this.coreRunner.stop();
163 }
164 }
165
166
167
168
169
170 static class ExitAction extends AbstractAction {
171
172 private static final long serialVersionUID = -589L;
173
174 ExitAction() {
175 super("Exit", GifResource.getIcon(Delete.class));
176 putValue(SHORT_DESCRIPTION,
177 "Quits this application immediately. ");
178 putValue(MNEMONIC_KEY, KeyEvent.VK_E);
179 putValue(ACCELERATOR_KEY,
180 KeyStroke.getKeyStroke(KeyEvent.VK_E,
181 ActionEvent.CTRL_MASK));
182 }
183
184 @edu.umd.cs.findbugs.annotations.SuppressWarnings
185 (value = "DM_EXIT",
186 justification = "To ensure safe exit " +
187 "not reached by throwing exception. " +
188 "Also Actions is not invoked by other code. ")
189 public void actionPerformed(ActionEvent event) {
190
191 System.exit(0);
192 }
193 }
194
195
196
197
198
199
200
201
202
203
204 class CoreRunner extends Thread {
205
206
207
208
209
210
211
212
213 private final RunNotifier notifier;
214
215
216
217
218 private final String testClassName;
219
220
221
222
223
224
225
226
227 CoreRunner(String testClassName) {
228 this.notifier = new RunNotifier();
229 this.notifier.addListener(Actions.this.listener);
230
231 this.testClassName = testClassName;
232 }
233
234
235
236
237 CoreRunner(CoreRunner other) {
238 this(other.testClassName);
239 }
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 public void run() {
256 Class<?> newTestClass = null;
257 try {
258 newTestClass = new TestCaseClassLoader()
259 .loadClass(this.testClassName, true);
260 } catch (ClassNotFoundException e) {
261 throw new IllegalStateException
262 ("Testclass '" + this.testClassName + "' disappeared. ");
263
264
265
266 }
267 assert newTestClass != null;
268
269 Request request = Request.aClass(newTestClass);
270
271 if (Actions.this.filter != null && Actions.this.filter.isTest()) {
272 request = request.filterWith(Actions.this.filter);
273 } else {
274 Actions.this.listener.testClassStructureLoaded
275 (request.getRunner().getDescription());
276 }
277
278 try {
279 run(request);
280 } catch (StoppedByUserException ee) {
281
282 Actions.this.listener.testRunAborted();
283 }
284
285
286 }
287
288
289 public void run(Request request) {
290 Runner runner = request.getRunner();
291 Result result = new Result();
292 RunListener listener = result.createListener();
293 this.notifier.addFirstListener(listener);
294 try {
295 this.notifier.fireTestRunStarted(runner.getDescription());
296 runner.run(this.notifier);
297 this.notifier.fireTestRunFinished(result);
298 } finally {
299 this.notifier.removeListener(listener);
300 }
301 }
302
303 public void pleaseStop() {
304 this.notifier.pleaseStop();
305 }
306
307 }
308
309
310
311
312
313
314
315
316
317 private final OpenAction openAction;
318
319
320
321
322 private final StartAction startAction;
323
324
325
326
327 private final StopAction stopAction;
328
329
330
331
332
333
334 private final BreakAction breakAction;
335
336 private final GUIRunner guiRunner;
337
338 private CoreRunner coreRunner;
339
340 private final ExtRunListener listener;
341
342
343
344
345
346
347
348
349 private boolean isRunning;
350
351
352
353
354
355
356
357
358
359
360
361 private Description filter;
362
363
364
365
366
367
368
369
370
371
372
373 @SuppressWarnings("checkstyle:nowhitespaceafter")
374 public Actions(String testClassName) {
375
376 this. openAction = new OpenAction();
377 this.startAction = new StartAction();
378 this. stopAction = new StopAction();
379 this.breakAction = new BreakAction();
380
381 this.guiRunner = new GUIRunner(this);
382 this.listener = new SeqRunListener(this.guiRunner);
383
384 this.coreRunner = new CoreRunner(testClassName);
385 this.isRunning = false;
386 this.filter = null;
387 }
388
389
390
391
392
393
394 private static boolean descShouldRun(Description desc,
395 Description desiredDesc) {
396 assert desc.isTest();
397 if (desiredDesc.isTest()) {
398 return desiredDesc.equals(desc);
399 }
400 for (Description each : desiredDesc.getChildren()) {
401 if (descShouldRun(desc, each)) {
402 return true;
403 }
404 }
405 return false;
406 }
407
408
409
410
411
412
413
414
415
416
417
418 public static Filter desc2filter(final Description desiredDesc) {
419 return new Filter() {
420 @Override
421 public boolean shouldRun(Description desc) {
422 return descShouldRun(desc, desiredDesc);
423 }
424
425 @Override
426 public String describe() {
427 return String.format("Methods %s",
428 desiredDesc.getDisplayName());
429 }
430 };
431 }
432
433
434
435
436
437
438
439
440
441
442
443
444 static void runTestClass(final String testClassName) {
445 Runnable guiCreator = new Runnable() {
446 public void run() {
447
448 new Actions(testClassName)
449 .startAction.actionPerformed(null);
450 }
451 };
452
453
454 SwingUtilities.invokeLater(guiCreator);
455 }
456
457
458
459
460
461
462
463
464 public static void runFromMain() {
465 runTestClass(new Throwable().getStackTrace()[1].getClassName());
466
467
468
469 }
470
471 GUIRunner getRunner() {
472 return this.guiRunner;
473 }
474
475
476
477
478
479
480
481 void setFilter(Description filter) {
482 assert filter != null;
483 this.filter = filter;
484 }
485
486
487
488
489
490
491
492
493
494
495 @SuppressWarnings("checkstyle:nowhitespaceafter")
496 void setEnableForRun(boolean isRunning) {
497 assert this.isRunning ^ isRunning;
498 this.isRunning = isRunning;
499 this. openAction.setEnabled(!this.isRunning);
500 this.startAction.setEnabled(!this.isRunning);
501 this. stopAction.setEnabled( this.isRunning);
502 this.breakAction.setEnabled( this.isRunning);
503 }
504
505 AbstractAction getOpenAction() {
506 return this.openAction;
507 }
508
509 AbstractAction getStartAction() {
510 return this.startAction;
511 }
512
513 AbstractAction getStopAction() {
514 return this.stopAction;
515 }
516
517 AbstractAction getBreakAction() {
518 return this.breakAction;
519 }
520
521 AbstractAction getExitAction() {
522 return new ExitAction();
523 }
524
525 public static void main(String[] args) {
526 runFromMain();
527 }
528 }