1 package org.codehaus.mojo.gwt.shell;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.plugin.MojoExecutionException;
24 import org.apache.maven.plugin.MojoFailureException;
25 import org.apache.maven.plugins.annotations.LifecyclePhase;
26 import org.apache.maven.plugins.annotations.Mojo;
27 import org.apache.maven.plugins.annotations.Parameter;
28 import org.apache.maven.plugins.annotations.ResolutionScope;
29 import org.apache.maven.surefire.report.ReporterManager;
30 import org.codehaus.mojo.gwt.test.MavenTestRunner;
31 import org.codehaus.mojo.gwt.test.TestTemplate;
32 import org.codehaus.plexus.util.StringUtils;
33
34 import java.io.File;
35 import java.net.URL;
36 import java.util.Collection;
37
38
39
40
41
42
43
44 @Mojo(name = "test", defaultPhase = LifecyclePhase.INTEGRATION_TEST, requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true)
45 public class TestMojo
46 extends AbstractGwtShellMojo
47 {
48
49
50
51
52
53 @Parameter(property = "skipTests")
54 private boolean skipTests;
55
56
57
58
59
60 @Deprecated
61 @Parameter(property = "maven.test.skip.exec")
62 private boolean skipExec;
63
64
65
66
67
68
69 @Parameter(property = "maven.test.skip")
70 private boolean skip;
71
72
73
74
75
76 @Parameter(property = "maven.test.failure.ignore")
77 private boolean testFailureIgnore;
78
79
80
81
82 @Parameter(defaultValue = "${project.build.directory}/www-test")
83 private String out;
84
85
86
87
88
89
90 @Deprecated
91 @Parameter(defaultValue = "false", property = "gwt.test.web")
92 private boolean webMode;
93
94
95
96
97
98
99 @Parameter(defaultValue = "false", property = "gwt.test.prod")
100 private boolean productionMode;
101
102
103
104
105
106
107 @Parameter(defaultValue = "htmlunit", property = "gwt.test.mode")
108 private String mode;
109
110
111
112
113
114
115
116 @Parameter(defaultValue = "FF38", property = "gwt.test.htmlunit")
117 private String htmlunit;
118
119
120
121
122
123
124
125 @Parameter(property = "gwt.test.selenium")
126 private String selenium;
127
128
129
130
131 @Parameter(defaultValue = "60")
132 @SuppressWarnings("unused")
133 private int testTimeOut;
134
135
136
137
138
139
140
141
142
143
144 @Parameter(defaultValue = "**/GwtTest*.java,**/Gwt*Suite.java")
145 protected String includes;
146
147
148
149
150 @Parameter
151 protected String excludes;
152
153
154
155
156 @Parameter(defaultValue = "${project.build.directory}/surefire-reports")
157 private File reportsDirectory;
158
159
160
161
162
163
164
165 @Parameter(property = "gwt.test.userAgents")
166 private String userAgents;
167
168
169
170
171
172
173
174
175
176 @Parameter(property = "gwt.test.batch")
177 private String batch;
178
179
180
181
182
183
184 @Parameter(defaultValue = "false", property = "gwt.test.showUi")
185 private boolean showUi;
186
187
188
189
190
191
192 @Parameter
193 private File workDir;
194
195
196
197
198
199
200 @Parameter
201 private File logDir;
202
203
204
205
206
207
208
209
210 @Parameter(defaultValue = "auto", property = "maven.compiler.source")
211 private String sourceLevel;
212
213
214
215
216
217
218 @Parameter(alias = "enableAssertions", defaultValue = "false")
219 private boolean checkAssertions;
220
221
222
223
224
225
226
227
228
229 @Parameter(defaultValue = "false", property = "gwt.disableClassMetadata")
230 private boolean disableClassMetadata;
231
232
233
234
235
236
237
238
239
240 @Parameter(defaultValue = "false", property = "gwt.disableCastChecking")
241 private boolean disableCastChecking;
242
243
244
245
246
247
248
249
250
251 @Parameter(defaultValue = "false", property = "gwt.disableRunAsync")
252 private boolean disableRunAsync;
253
254
255
256
257
258
259
260
261
262 @Parameter(defaultValue = "false", property = "gwt.draftCompiler")
263 private boolean draftCompile;
264
265
266
267
268
269
270 @Parameter(defaultValue = "true", property = "gwt.compiler.clusterFunctions")
271 private boolean clusterFunctions;
272
273
274
275
276
277
278
279 @Parameter(defaultValue = "true", property = "gwt.compiler.inlineLiteralParameters")
280 private boolean inlineLiteralParameters;
281
282
283
284
285
286
287 @Parameter(defaultValue = "true", property = "gwt.compiler.optimizeDataflow")
288 private boolean optimizeDataflow;
289
290
291
292
293
294
295 @Parameter(defaultValue = "true", property = "gwt.compiler.ordinalizeEnums")
296 private boolean ordinalizeEnums;
297
298
299
300
301
302
303
304
305 @Parameter(defaultValue = "true", property = "gwt.compiler.removeDuplicateFunctions")
306 private boolean removeDuplicateFunctions;
307
308
309
310
311
312
313
314
315
316
317
318
319 @Parameter(defaultValue = "-1", property = "gwt.compiler.optimizationLevel")
320 private int optimizationLevel;
321
322
323
324
325
326
327 @Parameter(defaultValue = "5", property = "gwt.testMethodTimeout")
328 private int testMethodTimeout;
329
330
331
332
333
334
335 @Parameter(defaultValue = "1", property = "gwt.testBeginTimeout")
336 private int testBeginTimeout;
337
338
339
340
341
342
343
344
345 @Parameter(defaultValue = "simple", property = "gwt.test.precompile")
346 private String precompile;
347
348
349
350
351
352
353 @Parameter(defaultValue = "1", property = "gwt.test.tries")
354 private int tries;
355
356
357
358
359
360
361
362
363
364
365 @Parameter
366 private String namespace;
367
368
369
370
371
372
373 @Parameter(alias = "compilePerFile", defaultValue = "false", property = "gwt.compiler.incremental")
374 private boolean incremental;
375
376
377
378
379
380
381 @Parameter(alias = "generateJsInteropExports", defaultValue = "false", property = "gwt.compiler.generateJsInteropExports")
382 private boolean generateJsInteropExports;
383
384
385 private int failures;
386
387 @Override
388 public void doExecute()
389 throws MojoExecutionException, MojoFailureException
390 {
391 if ( skip || skipTests || skipExec )
392 {
393 return;
394 }
395 new TestTemplate( getProject(), includes, excludes, new TestTemplate.CallBack()
396 {
397 public void doWithTest( File sourceDir, String test )
398 throws MojoExecutionException
399 {
400 forkToRunTest( test );
401 }
402 } );
403
404 if ( failures > 0 )
405 {
406 if ( testFailureIgnore )
407 {
408 getLog().error( "There are test failures.\n\nPlease refer to " + reportsDirectory
409 + " for the individual test results." );
410 }
411 else
412 {
413 throw new MojoExecutionException( "There were test failures." );
414 }
415 }
416 }
417
418
419
420
421
422
423
424 private void forkToRunTest( String test )
425 throws MojoExecutionException
426 {
427 test = test.substring( 0, test.length() - 5 );
428 test = StringUtils.replace( test, File.separator, "." );
429 try
430 {
431 File outFile = new File(out);
432 if (outFile.isAbsolute())
433 {
434 outFile.mkdirs();
435 }
436 else
437 {
438 new File( getProject().getBasedir(), out ).mkdirs();
439 }
440 try
441 {
442 JavaCommand cmd = createJavaCommand()
443 .setMainClass( MavenTestRunner.class.getName() );
444 if ( gwtSdkFirstInClasspath )
445 {
446 cmd.addToClasspath( getGwtUserJar() )
447 .addToClasspath( getGwtDevJar() );
448 }
449 cmd.addToClasspath( getClasspath( Artifact.SCOPE_TEST ) );
450 if ( !gwtSdkFirstInClasspath )
451 {
452 cmd.addToClasspath( getGwtUserJar() )
453 .addToClasspath( getGwtDevJar() );
454 }
455
456 addCompileSourceArtifacts( cmd );
457
458 cmd.arg( test );
459 cmd.systemProperty( "surefire.reports", reportsDirectory.getAbsolutePath() );
460 cmd.systemProperty( "gwt.args", StringUtils.escape(getGwtArgs()) );
461
462 cmd.execute();
463 }
464 catch ( JavaCommandException e )
465 {
466 getLog().warn("GWT test failure", e);
467 failures++;
468 }
469 }
470 catch ( Exception e )
471 {
472 throw new MojoExecutionException( "Failed to run GWT tests", e );
473 }
474 }
475
476 protected String getGwtArgs()
477 {
478 StringBuilder sb = new StringBuilder();
479 sb.append( "-war " ).append( quote( out ) );
480 sb.append( " -logLevel " ).append( quote( getLogLevel() ) );
481 sb.append( ( webMode || productionMode ) ? " -nodevMode" : " -devMode" );
482 sb.append( checkAssertions ? " -checkAssertions" : " -nocheckAssertions" );
483 sb.append( clusterFunctions ? " -XclusterFunctions" : " -XnoclusterFunctions" );
484 sb.append( disableCastChecking ? " -XnocheckCasts" : " -XcheckCasts" );
485 sb.append( disableClassMetadata ? " -XnoclassMetadata" : " -XclassMetadata" );
486 sb.append( disableRunAsync ? " -XnocodeSplitting" : " -XcodeSplitting" );
487 sb.append( draftCompile ? " -draftCompile" : " -nodraftCompile" );
488 sb.append( inlineLiteralParameters ? " -XinlineLiteralParameters" : " -XnoinlineLiteralParameters" );
489 sb.append( optimizeDataflow ? " -XoptimizeDataflow" : " -XnooptimizeDataflow" );
490 sb.append( ordinalizeEnums ? " -XordinalizeEnums" : " -XnoordinalizeEnums" );
491 sb.append( removeDuplicateFunctions ? " -XremoveDuplicateFunctions" : " -XnoremoveDuplicateFunctions" );
492 sb.append( showUi ? " -showUi" : " -noshowUi" );
493 sb.append( " -sourceLevel " ).append( quote( sourceLevel ) );
494 sb.append( " -testBeginTimeout " ).append( testBeginTimeout );
495 sb.append( " -testMethodTimeout ").append( testMethodTimeout );
496 sb.append( " -Xtries " ).append( tries );
497 sb.append( incremental ? " -incremental" : " -noincremental" );
498
499 if ( optimizationLevel >= 0 )
500 {
501 sb.append( " -optimize " ).append( optimizationLevel );
502 }
503 if ( precompile != null && !precompile.trim().isEmpty() )
504 {
505 sb.append( " -precompile " ).append( quote( precompile ) );
506 }
507 if ( logDir != null )
508 {
509 sb.append( " -logdir " ).append( quote( logDir.getAbsolutePath() ) );
510 }
511 if ( workDir != null )
512 {
513 sb.append( " -workDir " ).append( quote( workDir.getAbsolutePath() ) );
514 }
515 if ( namespace != null && !namespace.trim().isEmpty() )
516 {
517 sb.append( " -Xnamespace " ).append( quote( namespace ) );
518 }
519 if ( generateJsInteropExports )
520 {
521 sb.append( " -generateJsInteropExports" );
522 }
523 if ( mode.equalsIgnoreCase( "manual" ) )
524 {
525 sb.append( " -runStyle Manual:1" );
526 }
527 else if ( mode.equalsIgnoreCase( "htmlunit" ) )
528 {
529 sb.append( " -runStyle ").append( quote( "HtmlUnit:" + htmlunit ) );
530 }
531 else if ( mode.equalsIgnoreCase( "selenium" ) )
532 {
533 sb.append( " -runStyle ").append( quote( "Selenium:" + selenium ) );
534 }
535 else if ( !mode.trim().isEmpty() )
536 {
537 sb.append( " -runStyle ").append( quote( mode ) );
538 }
539 if ( userAgents != null && !userAgents.trim().isEmpty() )
540 {
541 sb.append( " -userAgents " ).append( quote( userAgents ) );
542 }
543 if ( batch != null && !batch.trim().isEmpty() )
544 {
545 sb.append( " -batch " ).append( quote( batch ) );
546 }
547
548
549 return sb.toString();
550 }
551
552 private String quote(String arg) {
553 return StringUtils.quoteAndEscape( arg, '"', new char[] { '"', ' ', '\t', '\r', '\n' } );
554 }
555
556 @Override
557 protected void postProcessClassPath( Collection<File> classpath )
558 {
559 classpath.add( getClassPathElementFor( TestMojo.class ) );
560 classpath.add( getClassPathElementFor( ReporterManager.class ) );
561 }
562
563
564
565
566
567 private File getClassPathElementFor( Class<?> clazz )
568 {
569 String classFile = clazz.getName().replace( '.', '/' ) + ".class";
570 ClassLoader cl = Thread.currentThread().getContextClassLoader();
571 if ( cl == null )
572 {
573 cl = getClass().getClassLoader();
574 }
575 URL url = cl.getResource( classFile );
576 getLog().debug( "getClassPathElementFor " + clazz.getName() + " file " + url.toString() );
577 String path = url.toString();
578
579 if ( path.startsWith( "jar:" ) )
580 {
581 path = path.substring( 4, path.indexOf( "!" ) );
582 }
583 else
584 {
585 path = path.substring( 0, path.length() - classFile.length() );
586 }
587 if ( path.startsWith( "file:" ) )
588 {
589 path = path.substring( 5 );
590
591 path = path.replace( "%20", " " );
592 }
593 File file = new File( path );
594 getLog().debug( "getClassPathElementFor " + clazz.getName() + " file " + file.getPath() );
595 return file;
596 }
597
598
599
600
601 public void setTestTimeOut( int testTimeOut )
602 {
603 setTimeOut( testTimeOut );
604 }
605
606 }