View Javadoc
1   package org.apache.maven.plugin.compiler;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static org.mockito.Matchers.startsWith;
23  import static org.mockito.Mockito.mock;
24  import static org.mockito.Mockito.never;
25  import static org.mockito.Mockito.verify;
26  import static org.mockito.Mockito.when;
27  
28  import java.io.File;
29  import java.net.URI;
30  import java.util.ArrayList;
31  import java.util.Arrays;
32  import java.util.Collections;
33  import java.util.HashSet;
34  import java.util.List;
35  import java.util.Set;
36  
37  import org.apache.maven.artifact.Artifact;
38  import org.apache.maven.artifact.handler.ArtifactHandler;
39  import org.apache.maven.execution.MavenSession;
40  import org.apache.maven.plugin.MojoExecution;
41  import org.apache.maven.plugin.compiler.stubs.CompilerManagerStub;
42  import org.apache.maven.plugin.compiler.stubs.DebugEnabledLog;
43  import org.apache.maven.plugin.descriptor.MojoDescriptor;
44  import org.apache.maven.plugin.descriptor.PluginDescriptor;
45  import org.apache.maven.plugin.logging.Log;
46  import org.apache.maven.plugin.testing.AbstractMojoTestCase;
47  import org.apache.maven.plugin.testing.stubs.ArtifactStub;
48  import org.apache.maven.project.MavenProject;
49  
50  public class CompilerMojoTestCase
51      extends AbstractMojoTestCase
52  {
53      
54      private String source = AbstractCompilerMojo.DEFAULT_SOURCE;
55  
56      private String target = AbstractCompilerMojo.DEFAULT_TARGET;
57      
58      @Override
59      protected void setUp()
60          throws Exception
61      {
62          super.setUp();
63          
64          String javaSpec = System.getProperty( "java.specification.version" );
65          // It is needed to set target/source to JDK 6 for JDK9 and JDK10
66          // cause this is the lowest version which is supported by those JDK's.
67          // The default source/target "5" is not supported anymore.
68          // See https://issues.apache.org/jira/browse/MCOMPILER-338
69          if ( "9".equals( javaSpec ) || "10".equals ( javaSpec ) )
70          {
71              source = "6";
72              target = "6";
73          }
74      }
75      
76      /**
77       * tests the ability of the plugin to compile a basic file
78       *
79       * @throws Exception
80       */
81      public void testCompilerBasic()
82          throws Exception
83      {
84          CompilerMojo compileMojo = getCompilerMojo( "target/test-classes/unit/compiler-basic-test/plugin-config.xml" );
85          
86          Log log = mock( Log.class );
87          
88          compileMojo.setLog( log );
89          
90          compileMojo.execute();
91  
92          File testClass = new File( compileMojo.getOutputDirectory(), "TestCompile0.class" );
93  
94          assertTrue( testClass.exists() );
95  
96          TestCompilerMojo testCompileMojo =
97              getTestCompilerMojo( compileMojo, "target/test-classes/unit/compiler-basic-test/plugin-config.xml" );
98  
99          testCompileMojo.execute();
100 
101         Artifact projectArtifact = (Artifact) getVariableValueFromObject( compileMojo, "projectArtifact" );
102         assertNotNull( "MCOMPILER-94: artifact file should only be null if there is nothing to compile",
103                        projectArtifact.getFile() );
104 
105         testClass = new File( testCompileMojo.getOutputDirectory(), "TestCompile0Test.class" );
106         
107         verify( log ).warn( startsWith( "No explicit value set for target or release!" ) );
108 
109         assertTrue( testClass.exists() );
110     }
111     
112     public void testCompilerBasicSourceTarget()
113                     throws Exception
114     {
115         CompilerMojo compileMojo = getCompilerMojo( "target/test-classes/unit/compiler-basic-sourcetarget/plugin-config.xml" );
116         
117         Log log = mock( Log.class );
118         
119         compileMojo.setLog( log );
120         
121         compileMojo.execute();
122         
123         verify( log, never() ).warn( startsWith( "No explicit value set for target or release!" ) );
124     }
125 
126     /**
127      * tests the ability of the plugin to respond to empty source
128      *
129      * @throws Exception
130      */
131     public void testCompilerEmptySource()
132         throws Exception
133     {
134         CompilerMojo compileMojo =
135             getCompilerMojo( "target/test-classes/unit/compiler-empty-source-test/plugin-config.xml" );
136 
137         compileMojo.execute();
138 
139         assertFalse( compileMojo.getOutputDirectory().exists() );
140 
141         Artifact projectArtifact = (Artifact) getVariableValueFromObject( compileMojo, "projectArtifact" );
142         assertNull( "MCOMPILER-94: artifact file should be null if there is nothing to compile",
143                     projectArtifact.getFile() );
144 
145         TestCompilerMojo testCompileMojo =
146             getTestCompilerMojo( compileMojo, "target/test-classes/unit/compiler-empty-source-test/plugin-config.xml" );
147 
148         testCompileMojo.execute();
149 
150         assertFalse( testCompileMojo.getOutputDirectory().exists() );
151     }
152 
153     /**
154      * tests the ability of the plugin to respond to includes and excludes correctly
155      *
156      * @throws Exception
157      */
158     public void testCompilerIncludesExcludes()
159         throws Exception
160     {
161         CompilerMojo compileMojo =
162             getCompilerMojo( "target/test-classes/unit/compiler-includes-excludes-test/plugin-config.xml" );
163 
164         Set<String> includes = new HashSet<String>();
165         includes.add( "**/TestCompile4*.java" );
166         setVariableValueToObject( compileMojo, "includes", includes );
167 
168         Set<String> excludes = new HashSet<String>();
169         excludes.add( "**/TestCompile2*.java" );
170         excludes.add( "**/TestCompile3*.java" );
171         setVariableValueToObject( compileMojo, "excludes", excludes );
172 
173         compileMojo.execute();
174 
175         File testClass = new File( compileMojo.getOutputDirectory(), "TestCompile2.class" );
176         assertFalse( testClass.exists() );
177 
178         testClass = new File( compileMojo.getOutputDirectory(), "TestCompile3.class" );
179         assertFalse( testClass.exists() );
180 
181         testClass = new File( compileMojo.getOutputDirectory(), "TestCompile4.class" );
182         assertTrue( testClass.exists() );
183 
184         TestCompilerMojo testCompileMojo = getTestCompilerMojo( compileMojo,
185                                                                 "target/test-classes/unit/compiler-includes-excludes-test/plugin-config.xml" );
186 
187         setVariableValueToObject( testCompileMojo, "testIncludes", includes );
188         setVariableValueToObject( testCompileMojo, "testExcludes", excludes );
189 
190         testCompileMojo.execute();
191 
192         testClass = new File( testCompileMojo.getOutputDirectory(), "TestCompile2TestCase.class" );
193         assertFalse( testClass.exists() );
194 
195         testClass = new File( testCompileMojo.getOutputDirectory(), "TestCompile3TestCase.class" );
196         assertFalse( testClass.exists() );
197 
198         testClass = new File( testCompileMojo.getOutputDirectory(), "TestCompile4TestCase.class" );
199         assertTrue( testClass.exists() );
200     }
201 
202     /**
203      * tests the ability of the plugin to fork and successfully compile
204      *
205      * @throws Exception
206      */
207     public void testCompilerFork()
208         throws Exception
209     {
210         CompilerMojo compileMojo = getCompilerMojo( "target/test-classes/unit/compiler-fork-test/plugin-config.xml" );
211 
212         // JAVA_HOME doesn't have to be on the PATH.
213         setVariableValueToObject( compileMojo, "executable",  new File( System.getenv( "JAVA_HOME" ), "bin/javac" ).getPath() );
214 
215         compileMojo.execute();
216 
217         File testClass = new File( compileMojo.getOutputDirectory(), "TestCompile1.class" );
218         assertTrue( testClass.exists() );
219 
220         TestCompilerMojo testCompileMojo =
221             getTestCompilerMojo( compileMojo, "target/test-classes/unit/compiler-fork-test/plugin-config.xml" );
222 
223         // JAVA_HOME doesn't have to be on the PATH.
224         setVariableValueToObject( testCompileMojo, "executable",  new File( System.getenv( "JAVA_HOME" ), "bin/javac" ).getPath() );
225 
226         testCompileMojo.execute();
227 
228         testClass = new File( testCompileMojo.getOutputDirectory(), "TestCompile1TestCase.class" );
229         assertTrue( testClass.exists() );
230     }
231 
232     public void testOneOutputFileForAllInput()
233         throws Exception
234     {
235         CompilerMojo compileMojo =
236             getCompilerMojo( "target/test-classes/unit/compiler-one-output-file-test/plugin-config.xml" );
237 
238         setVariableValueToObject( compileMojo, "compilerManager", new CompilerManagerStub() );
239 
240         compileMojo.execute();
241 
242         File testClass = new File( compileMojo.getOutputDirectory(), "compiled.class" );
243         assertTrue( testClass.exists() );
244 
245         TestCompilerMojo testCompileMojo = getTestCompilerMojo( compileMojo,
246                                                                 "target/test-classes/unit/compiler-one-output-file-test/plugin-config.xml" );
247 
248         setVariableValueToObject( testCompileMojo, "compilerManager", new CompilerManagerStub() );
249 
250         testCompileMojo.execute();
251 
252         testClass = new File( testCompileMojo.getOutputDirectory(), "compiled.class" );
253         assertTrue( testClass.exists() );
254     }
255 
256     public void testCompilerArgs()
257         throws Exception
258     {
259         CompilerMojo compileMojo = getCompilerMojo( "target/test-classes/unit/compiler-args-test/plugin-config.xml" );
260 
261         setVariableValueToObject( compileMojo, "compilerManager", new CompilerManagerStub() );
262 
263         compileMojo.execute();
264 
265         File testClass = new File( compileMojo.getOutputDirectory(), "compiled.class" );
266         assertTrue( testClass.exists() );
267         assertEquals( Arrays.asList( "key1=value1","-Xlint","-my&special:param-with+chars/not>allowed_in_XML_element_names" ), compileMojo.compilerArgs );
268     }
269 
270     public void testOneOutputFileForAllInput2()
271         throws Exception
272     {
273         CompilerMojo compileMojo =
274             getCompilerMojo( "target/test-classes/unit/compiler-one-output-file-test2/plugin-config.xml" );
275 
276         setVariableValueToObject( compileMojo, "compilerManager", new CompilerManagerStub() );
277 
278         Set<String> includes = new HashSet<String>();
279         includes.add( "**/TestCompile4*.java" );
280         setVariableValueToObject( compileMojo, "includes", includes );
281 
282         Set<String> excludes = new HashSet<String>();
283         excludes.add( "**/TestCompile2*.java" );
284         excludes.add( "**/TestCompile3*.java" );
285         setVariableValueToObject( compileMojo, "excludes", excludes );
286 
287         compileMojo.execute();
288 
289         File testClass = new File( compileMojo.getOutputDirectory(), "compiled.class" );
290         assertTrue( testClass.exists() );
291 
292         TestCompilerMojo testCompileMojo = getTestCompilerMojo( compileMojo,
293                                                                 "target/test-classes/unit/compiler-one-output-file-test2/plugin-config.xml" );
294 
295         setVariableValueToObject( testCompileMojo, "compilerManager", new CompilerManagerStub() );
296         setVariableValueToObject( testCompileMojo, "testIncludes", includes );
297         setVariableValueToObject( testCompileMojo, "testExcludes", excludes );
298 
299         testCompileMojo.execute();
300 
301         testClass = new File( testCompileMojo.getOutputDirectory(), "compiled.class" );
302         assertTrue( testClass.exists() );
303     }
304 
305     public void testCompileFailure()
306         throws Exception
307     {
308         CompilerMojo compileMojo = getCompilerMojo( "target/test-classes/unit/compiler-fail-test/plugin-config.xml" );
309 
310         setVariableValueToObject( compileMojo, "compilerManager", new CompilerManagerStub( true ) );
311 
312         try
313         {
314             compileMojo.execute();
315 
316             fail( "Should throw an exception" );
317         }
318         catch ( CompilationFailureException e )
319         {
320             //expected
321         }
322     }
323 
324     public void testCompileFailOnError()
325         throws Exception
326     {
327         CompilerMojo compileMojo =
328             getCompilerMojo( "target/test-classes/unit/compiler-failonerror-test/plugin-config.xml" );
329 
330         setVariableValueToObject( compileMojo, "compilerManager", new CompilerManagerStub( true ) );
331 
332         try
333         {
334             compileMojo.execute();
335             assertTrue( true );
336         }
337         catch ( CompilationFailureException e )
338         {
339             fail( "The compilation error should have been consumed because failOnError = false" );
340         }
341     }
342     
343     /**
344      * Tests that setting 'skipMain' to true skips compilation of the main Java source files, but that test Java source
345      * files are still compiled.
346      * @throws Exception
347      */
348     public void testCompileSkipMain()
349         throws Exception
350     {
351         CompilerMojo compileMojo = getCompilerMojo( "target/test-classes/unit/compiler-skip-main/plugin-config.xml" );
352         setVariableValueToObject( compileMojo, "skipMain", true );
353         compileMojo.execute();
354         File testClass = new File( compileMojo.getOutputDirectory(), "TestSkipMainCompile0.class" );
355         assertFalse( testClass.exists() );
356 
357         TestCompilerMojo testCompileMojo =
358             getTestCompilerMojo( compileMojo, "target/test-classes/unit/compiler-skip-main/plugin-config.xml" );
359         testCompileMojo.execute();
360         testClass = new File( testCompileMojo.getOutputDirectory(), "TestSkipMainCompile0Test.class" );
361         assertTrue( testClass.exists() );
362     }
363     
364     /**
365      * Tests that setting 'skip' to true skips compilation of the test Java source files, but that main Java source
366      * files are still compiled.
367      * @throws Exception
368      */
369     public void testCompileSkipTest()
370         throws Exception
371     {
372         CompilerMojo compileMojo = getCompilerMojo( "target/test-classes/unit/compiler-skip-test/plugin-config.xml" );
373         compileMojo.execute();
374         File testClass = new File( compileMojo.getOutputDirectory(), "TestSkipTestCompile0.class" );
375         assertTrue( testClass.exists() );
376 
377         TestCompilerMojo testCompileMojo =
378             getTestCompilerMojo( compileMojo, "target/test-classes/unit/compiler-skip-test/plugin-config.xml" );
379         setVariableValueToObject( testCompileMojo, "skip", true );
380         testCompileMojo.execute();
381         testClass = new File( testCompileMojo.getOutputDirectory(), "TestSkipTestCompile0Test.class" );
382         assertFalse( testClass.exists() );
383     }
384 
385     private CompilerMojo getCompilerMojo( String pomXml )
386         throws Exception
387     {
388         File testPom = new File( getBasedir(), pomXml );
389 
390         CompilerMojo mojo = (CompilerMojo) lookupMojo( "compile", testPom );
391 
392         setVariableValueToObject( mojo, "log", new DebugEnabledLog() );
393         setVariableValueToObject( mojo, "projectArtifact", new ArtifactStub() );
394         setVariableValueToObject( mojo, "compilePath", Collections.EMPTY_LIST );
395         setVariableValueToObject( mojo, "session", getMockMavenSession() );
396         setVariableValueToObject( mojo, "project", getMockMavenProject() );
397         setVariableValueToObject( mojo, "mojoExecution", getMockMojoExecution() );
398         setVariableValueToObject( mojo, "source", source );
399         setVariableValueToObject( mojo, "target", target );
400 
401         return mojo;
402     }
403 
404     private TestCompilerMojo getTestCompilerMojo( CompilerMojo compilerMojo, String pomXml )
405         throws Exception
406     {
407         File testPom = new File( getBasedir(), pomXml );
408 
409         TestCompilerMojo mojo = (TestCompilerMojo) lookupMojo( "testCompile", testPom );
410 
411         setVariableValueToObject( mojo, "log", new DebugEnabledLog() );
412 
413         File buildDir = (File) getVariableValueFromObject( compilerMojo, "buildDirectory" );
414         File testClassesDir = new File( buildDir, "test-classes" );
415         setVariableValueToObject( mojo, "outputDirectory", testClassesDir );
416 
417         List<String> testClasspathList = new ArrayList<String>();
418         
419         Artifact junitArtifact = mock( Artifact.class );
420         ArtifactHandler handler = mock( ArtifactHandler.class );
421         when( handler.isAddedToClasspath() ).thenReturn( true );
422         when( junitArtifact.getArtifactHandler() ).thenReturn( handler );
423 
424         File artifactFile;
425         String localRepository = System.getProperty( "localRepository" );
426         if ( localRepository != null )
427         {
428             artifactFile = new File( localRepository, "junit/junit/3.8.1/junit-3.8.1.jar" );
429         }
430         else
431         {
432             // for IDE
433             String junitURI = org.junit.Test.class.getResource( "Test.class" ).toURI().toString();
434             junitURI = junitURI.substring( "jar:".length(), junitURI.indexOf( '!' ) );
435             artifactFile = new File( URI.create( junitURI ) );
436         }
437         when ( junitArtifact.getFile() ).thenReturn( artifactFile );
438         
439         testClasspathList.add( artifactFile.getAbsolutePath() );
440         testClasspathList.add( compilerMojo.getOutputDirectory().getPath() );
441 
442         String testSourceRoot = testPom.getParent() + "/src/test/java";
443         setVariableValueToObject( mojo, "compileSourceRoots", Collections.singletonList( testSourceRoot ) );
444 
445         MavenProject project = getMockMavenProject();
446         project.setFile( testPom );
447         project.addCompileSourceRoot("/src/main/java" );
448         project.setArtifacts( Collections.singleton( junitArtifact )  );
449         project.getBuild().setOutputDirectory( new File( buildDir, "classes" ).getAbsolutePath() );
450         setVariableValueToObject( mojo, "project", project );
451         setVariableValueToObject( mojo, "compilePath", Collections.EMPTY_LIST );
452         setVariableValueToObject( mojo, "testPath", testClasspathList );
453         setVariableValueToObject( mojo, "session", getMockMavenSession() );
454         setVariableValueToObject( mojo, "mojoExecution", getMockMojoExecution() );
455         setVariableValueToObject( mojo, "source", source );
456         setVariableValueToObject( mojo, "target", target );
457 
458         return mojo;
459     }
460     
461     private MavenProject getMockMavenProject()
462     {
463         MavenProject mp = new MavenProject();
464         mp.getBuild().setDirectory( "target" );
465         mp.getBuild().setOutputDirectory( "target/classes" );
466         mp.getBuild().setSourceDirectory( "src/main/java" );
467         mp.getBuild().setTestOutputDirectory( "target/test-classes" );
468         return mp;
469     }
470 
471     private MavenSession getMockMavenSession()
472     {
473         MavenSession session = mock( MavenSession.class );
474         // when( session.getPluginContext( isA(PluginDescriptor.class), isA(MavenProject.class) ) ).thenReturn(
475         // Collections.emptyMap() );
476         when( session.getCurrentProject() ).thenReturn( getMockMavenProject() );
477         return session;
478     }
479 
480     private MojoExecution getMockMojoExecution()
481     {
482         MojoDescriptor md = new MojoDescriptor();
483         md.setGoal( "compile" );
484 
485         MojoExecution me = new MojoExecution( md );
486 
487         PluginDescriptor pd = new PluginDescriptor();
488         pd.setArtifactId( "maven-compiler-plugin" );
489         md.setPluginDescriptor( pd );
490 
491         return me;
492     }
493 }