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
163 Actions.this.coreRunner.stop();
164 }
165 }
166
167
168
169
170
171 static class ExitAction extends AbstractAction {
172
173 private static final long serialVersionUID = -589L;
174
175 ExitAction() {
176 super("Exit", GifResource.getIcon(Delete.class));
177 putValue(SHORT_DESCRIPTION,
178 "Quits this application immediately. ");
179 putValue(MNEMONIC_KEY, KeyEvent.VK_E);
180 putValue(ACCELERATOR_KEY,
181 KeyStroke.getKeyStroke(KeyEvent.VK_E,
182 ActionEvent.CTRL_MASK));
183 }
184
185 @edu.umd.cs.findbugs.annotations.SuppressWarnings
186 (value = "DM_EXIT",
187 justification = "To ensure safe exit " +
188 "not reached by throwing exception. " +
189 "Also Actions is not invoked by other code. ")
190 public void actionPerformed(ActionEvent event) {
191
192 System.exit(0);
193 }
194 }
195
196
197
198
199
200
201
202
203
204
205 class CoreRunner extends Thread {
206
207
208
209
210
211
212
213
214 private final RunNotifier notifier;
215
216
217
218
219 private final String testClassName;
220
221
222
223
224
225
226
227
228 CoreRunner(String testClassName) {
229 this.notifier = new RunNotifier();
230 this.notifier.addListener(Actions.this.listener);
231
232 this.testClassName = testClassName;
233 }
234
235
236
237
238 CoreRunner(CoreRunner other) {
239 this(other.testClassName);
240 }
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 public void run() {
257 Class<?> newTestClass = null;
258 try {
259 newTestClass = new TestCaseClassLoader()
260 .loadClass(this.testClassName, true);
261 } catch (ClassNotFoundException e) {
262 throw new IllegalStateException
263 ("Testclass '" + this.testClassName + "' disappeared. ");
264
265
266
267 }
268 assert newTestClass != null;
269
270 Request request = Request.aClass(newTestClass);
271
272 if (Actions.this.filter != null && Actions.this.filter.isTest()) {
273 request = request.filterWith(Actions.this.filter);
274 } else {
275 Actions.this.listener.testClassStructureLoaded
276 (request.getRunner().getDescription());
277 }
278
279 try {
280 run(request);
281 } catch (StoppedByUserException ee) {
282
283 Actions.this.listener.testRunAborted();
284 }
285
286
287 }
288
289
290 public void run(Request request) {
291 Runner runner = request.getRunner();
292 Result result = new Result();
293 RunListener listener = result.createListener();
294 this.notifier.addFirstListener(listener);
295 try {
296 this.notifier.fireTestRunStarted(runner.getDescription());
297 runner.run(this.notifier);
298 this.notifier.fireTestRunFinished(result);
299 } finally {
300 this.notifier.removeListener(listener);
301 }
302 }
303
304 public void pleaseStop() {
305 this.notifier.pleaseStop();
306 }
307
308 }
309
310
311
312
313
314
315
316
317
318 private final OpenAction openAction;
319
320
321
322
323 private final StartAction startAction;
324
325
326
327
328 private final StopAction stopAction;
329
330
331
332
333
334
335 private final BreakAction breakAction;
336
337 private final GUIRunner guiRunner;
338
339 private CoreRunner coreRunner;
340
341 private final ExtRunListener listener;
342
343
344
345
346
347
348
349
350 private boolean isRunning;
351
352
353
354
355
356
357
358
359
360
361
362 private Description filter;
363
364
365
366
367
368
369
370
371
372
373
374 @SuppressWarnings("checkstyle:nowhitespaceafter")
375 public Actions(String testClassName) {
376
377 this. openAction = new OpenAction();
378 this.startAction = new StartAction();
379 this. stopAction = new StopAction();
380 this.breakAction = new BreakAction();
381
382 this.guiRunner = new GUIRunner(this);
383 this.listener = new SeqRunListener(this.guiRunner);
384
385 this.coreRunner = new CoreRunner(testClassName);
386 this.isRunning = false;
387 this.filter = null;
388 }
389
390
391
392
393
394
395 private static boolean descShouldRun(Description desc,
396 Description desiredDesc) {
397 assert desc.isTest();
398 if (desiredDesc.isTest()) {
399 return desiredDesc.equals(desc);
400 }
401 for (Description each : desiredDesc.getChildren()) {
402 if (descShouldRun(desc, each)) {
403 return true;
404 }
405 }
406 return false;
407 }
408
409
410
411
412
413
414
415
416
417
418
419 public static Filter desc2filter(final Description desiredDesc) {
420 return new Filter() {
421 @Override
422 public boolean shouldRun(Description desc) {
423 return descShouldRun(desc, desiredDesc);
424 }
425
426 @Override
427 public String describe() {
428 return String.format("Methods %s",
429 desiredDesc.getDisplayName());
430 }
431 };
432 }
433
434
435
436
437
438
439
440
441
442
443
444
445 static void runTestClass(final String testClassName) {
446 Runnable guiCreator = new Runnable() {
447 public void run() {
448
449 new Actions(testClassName)
450 .startAction.actionPerformed(null);
451 }
452 };
453
454
455 SwingUtilities.invokeLater(guiCreator);
456 }
457
458
459
460
461
462
463
464
465 public static void runFromMain() {
466 runTestClass(new Throwable().getStackTrace()[1].getClassName());
467
468
469
470 }
471
472 GUIRunner getRunner() {
473 return this.guiRunner;
474 }
475
476
477
478
479
480
481
482 void setFilter(Description filter) {
483 assert filter != null;
484 this.filter = filter;
485 }
486
487
488
489
490
491
492
493
494
495
496 @SuppressWarnings("checkstyle:nowhitespaceafter")
497 void setEnableForRun(boolean isRunning) {
498 assert this.isRunning ^ isRunning;
499 this.isRunning = isRunning;
500 this. openAction.setEnabled(!this.isRunning);
501 this.startAction.setEnabled(!this.isRunning);
502 this. stopAction.setEnabled( this.isRunning);
503 this.breakAction.setEnabled( this.isRunning);
504 }
505
506 AbstractAction getOpenAction() {
507 return this.openAction;
508 }
509
510 AbstractAction getStartAction() {
511 return this.startAction;
512 }
513
514 AbstractAction getStopAction() {
515 return this.stopAction;
516 }
517
518 AbstractAction getBreakAction() {
519 return this.breakAction;
520 }
521
522 AbstractAction getExitAction() {
523 return new ExitAction();
524 }
525
526 public static void main(String[] args) {
527 runFromMain();
528 }
529 }