This is an automated email from the ASF dual-hosted git repository. sor pushed a commit to branch MCOMPILER-341 in repository https://gitbox.apache.org/repos/asf/maven-compiler-plugin.git
commit 570bf47017750fff4d44e370bcc5521bddcee58b Author: Christian Stein <sormu...@gmail.com> AuthorDate: Tue Apr 17 14:30:50 2018 +0200 Introduce white-box testing modules Prior to this commit module descriptors `module-info.java` were not compiled by the TestCompilerMojo. This commit introduces support for test sources organized with module descriptors. See motivation: https://twitter.com/rfscholte/status/927132319374331904 --- .../plugin/compiler/AbstractCompilerMojo.java | 5 +- .../maven/plugin/compiler/TestCompilerMojo.java | 156 +++++++++++++++------ .../plugin/compiler/CompilerMojoTestCase.java | 27 ++++ .../unit/compiler-jpms-test/plugin-config.xml | 38 +++++ .../src/main/java/foo/TestJpms0.java | 31 ++++ .../src/main/java/module-info.java | 22 +++ .../src/test/java/foo/TestJpms0Test.java | 30 ++++ .../src/test/java/module-info.java | 22 +++ 8 files changed, 288 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java index 294ae23..31179d7 100644 --- a/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java +++ b/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java @@ -1005,7 +1005,10 @@ public abstract class AbstractCompilerMojo if ( descriptor == null ) { - getLog().warn( "Can't locate " + file ); + if ( ! Files.isDirectory( Paths.get ( file ) ) ) + { + getLog().warn( "Can't locate " + file ); + } } else if ( !values[0].equals( descriptor.name() ) ) { diff --git a/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java index 78b0a0b..6fa080e 100644 --- a/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java +++ b/src/main/java/org/apache/maven/plugin/compiler/TestCompilerMojo.java @@ -21,6 +21,8 @@ package org.apache.maven.plugin.compiler; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -207,22 +209,84 @@ public class TestCompilerMojo protected void preparePaths( Set<File> sourceFiles ) { File mainOutputDirectory = new File( getProject().getBuild().getOutputDirectory() ); - - File mainModuleDescriptor = new File( mainOutputDirectory, "module-info.class" ); - boolean hasTestModuleDescriptor = false; - - // Go through the source files to respect includes/excludes + File mainModuleDescriptorClassFile = new File( mainOutputDirectory, "module-info.class" ); + JavaModuleDescriptor mainModuleDescriptor = null; + + File testModuleDescriptorJavaFile = new File( "module-info.java" ); + JavaModuleDescriptor testModuleDescriptor = null; + + // Go through the source files to respect includes/excludes for ( File sourceFile : sourceFiles ) { // @todo verify if it is the root of a sourcedirectory? if ( "module-info.java".equals( sourceFile.getName() ) ) { - hasTestModuleDescriptor = true; + testModuleDescriptorJavaFile = sourceFile; break; } } - + + // Get additional information from the main module descriptor, if available + if ( mainModuleDescriptorClassFile.exists() ) + { + ResolvePathsResult<String> result; + + try + { + ResolvePathsRequest<String> request = + ResolvePathsRequest.withStrings( testPath ) + .setMainModuleDescriptor( mainModuleDescriptorClassFile.getAbsolutePath() ); + + Toolchain toolchain = getToolchain(); + if ( toolchain != null && toolchain instanceof DefaultJavaToolChain ) + { + request.setJdkHome( ( (DefaultJavaToolChain) toolchain ).getJavaHome() ); + } + + result = locationManager.resolvePaths( request ); + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + + mainModuleDescriptor = result.getMainModuleDescriptor(); + + pathElements = new LinkedHashMap<String, JavaModuleDescriptor>( result.getPathElements().size() ); + pathElements.putAll( result.getPathElements() ); + + modulepathElements = result.getModulepathElements().keySet(); + classpathElements = result.getClasspathElements(); + } + + // Get additional information from the test module descriptor, if available + if ( testModuleDescriptorJavaFile.exists() ) + { + ResolvePathsResult<String> result; + + try + { + ResolvePathsRequest<String> request = + ResolvePathsRequest.withStrings( testPath ) + .setMainModuleDescriptor( testModuleDescriptorJavaFile.getAbsolutePath() ); + + Toolchain toolchain = getToolchain(); + if ( toolchain != null && toolchain instanceof DefaultJavaToolChain ) + { + request.setJdkHome( ( (DefaultJavaToolChain) toolchain ).getJavaHome() ); + } + + result = locationManager.resolvePaths( request ); + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + + testModuleDescriptor = result.getMainModuleDescriptor(); + } + if ( release != null ) { if ( Integer.valueOf( release ) < 9 ) @@ -241,17 +305,54 @@ public class TestCompilerMojo return; } - if ( hasTestModuleDescriptor ) + if ( testModuleDescriptor != null ) { modulepathElements = testPath; classpathElements = Collections.emptyList(); - if ( mainModuleDescriptor.exists() ) + if ( mainModuleDescriptor != null ) { - // maybe some extra analysis required + if ( getLog().isDebugEnabled() ) + { + getLog().debug( "Main and test module descriptors exist:" ); + getLog().debug( " main module = " + mainModuleDescriptor.name() ); + getLog().debug( " test module = " + testModuleDescriptor.name() ); + } + + if ( testModuleDescriptor.name().equals( mainModuleDescriptor.name() ) ) + { + if ( compilerArgs == null ) + { + compilerArgs = new ArrayList<String>(); + } + compilerArgs.add( "--patch-module" ); + + StringBuilder patchModuleValue = new StringBuilder(); + patchModuleValue.append( testModuleDescriptor.name() ); + patchModuleValue.append( '=' ); + + for ( String root : getProject().getCompileSourceRoots() ) + { + if ( Files.exists( Paths.get( root ) ) ) + { + patchModuleValue.append( root ).append( PS ); + } + } + + compilerArgs.add( patchModuleValue.toString() ); + } + else + { + getLog().debug( "Black-box testing - all is ready to compile" ); + } } else { + // No main binaries available? Means we're a test-only project. + if ( !mainOutputDirectory.exists() ) + { + return; + } // very odd // Means that main sources must be compiled with -modulesource and -Xmodule:<moduleName> // However, this has a huge impact since you can't simply use it as a classpathEntry @@ -262,44 +363,15 @@ public class TestCompilerMojo } else { - if ( mainModuleDescriptor.exists() ) + if ( mainModuleDescriptor != null ) { - ResolvePathsResult<String> result; - - try - { - ResolvePathsRequest<String> request = - ResolvePathsRequest.withStrings( testPath ) - .setMainModuleDescriptor( mainModuleDescriptor.getAbsolutePath() ); - - Toolchain toolchain = getToolchain(); - if ( toolchain != null && toolchain instanceof DefaultJavaToolChain ) - { - request.setJdkHome( ( (DefaultJavaToolChain) toolchain ).getJavaHome() ); - } - - result = locationManager.resolvePaths( request ); - } - catch ( IOException e ) - { - throw new RuntimeException( e ); - } - - JavaModuleDescriptor moduleDescriptor = result.getMainModuleDescriptor(); - - pathElements = new LinkedHashMap<String, JavaModuleDescriptor>( result.getPathElements().size() ); - pathElements.putAll( result.getPathElements() ); - - modulepathElements = result.getModulepathElements().keySet(); - classpathElements = result.getClasspathElements(); - if ( compilerArgs == null ) { compilerArgs = new ArrayList<String>(); } compilerArgs.add( "--patch-module" ); - StringBuilder patchModuleValue = new StringBuilder( moduleDescriptor.name() ) + StringBuilder patchModuleValue = new StringBuilder( mainModuleDescriptor.name() ) .append( '=' ) .append( mainOutputDirectory ) .append( PS ); @@ -311,7 +383,7 @@ public class TestCompilerMojo compilerArgs.add( patchModuleValue.toString() ); compilerArgs.add( "--add-reads" ); - compilerArgs.add( moduleDescriptor.name() + "=ALL-UNNAMED" ); + compilerArgs.add( mainModuleDescriptor.name() + "=ALL-UNNAMED" ); } else { diff --git a/src/test/java/org/apache/maven/plugin/compiler/CompilerMojoTestCase.java b/src/test/java/org/apache/maven/plugin/compiler/CompilerMojoTestCase.java index dfa5ec5..0d674ae 100644 --- a/src/test/java/org/apache/maven/plugin/compiler/CompilerMojoTestCase.java +++ b/src/test/java/org/apache/maven/plugin/compiler/CompilerMojoTestCase.java @@ -100,6 +100,31 @@ public class CompilerMojoTestCase } /** + * tests the ability of the plugin to compile a jpms project + * + * @throws Exception + */ + public void testCompilerJpms() + throws Exception + { + CompilerMojo compileMojo = getCompilerMojo( "target/test-classes/unit/compiler-jpms-test/plugin-config.xml" ); + + compileMojo.execute(); + + assertTrue( new File( compileMojo.getOutputDirectory(), "module-info.class" ).exists() ); + assertTrue( new File( compileMojo.getOutputDirectory(), "foo/TestJpms0.class" ).exists() ); + + TestCompilerMojo testCompileMojo = + getTestCompilerMojo( compileMojo, "target/test-classes/unit/compiler-jpms-test/plugin-config.xml" ); + + testCompileMojo.execute(); + + assertTrue( new File( testCompileMojo.getOutputDirectory(), "module-info.class" ).exists() ); + assertTrue( new File( testCompileMojo.getOutputDirectory(), "foo/TestJpms0.class" ).exists() ); + assertTrue( new File( testCompileMojo.getOutputDirectory(), "foo/TestJpms0Test.class" ).exists() ); + } + + /** * tests the ability of the plugin to respond to empty source * * @throws Exception @@ -419,6 +444,8 @@ public class CompilerMojoTestCase setVariableValueToObject( mojo, "compileSourceRoots", Collections.singletonList( testSourceRoot ) ); MavenProject project = getMockMavenProject(); + project.setFile( testPom ); + project.addCompileSourceRoot("/src/main/java" ); project.setArtifacts( Collections.singleton( junitArtifact ) ); project.getBuild().setOutputDirectory( new File( buildDir, "classes" ).getAbsolutePath() ); setVariableValueToObject( mojo, "project", project ); diff --git a/src/test/resources/unit/compiler-jpms-test/plugin-config.xml b/src/test/resources/unit/compiler-jpms-test/plugin-config.xml new file mode 100644 index 0000000..631ba01 --- /dev/null +++ b/src/test/resources/unit/compiler-jpms-test/plugin-config.xml @@ -0,0 +1,38 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, + ~ software distributed under the License is distributed on an + ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + ~ KIND, either express or implied. See the License for the + ~ specific language governing permissions and limitations + ~ under the License. + --> + +<project> + <build> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <compileSourceRoots> + <compileSourceRoot>${basedir}/target/test-classes/unit/compiler-jpms-test/src/main/java</compileSourceRoot> + </compileSourceRoots> + <compilerId>javac</compilerId> + <debug>true</debug> + <release>9</release> + <outputDirectory>${basedir}/target/test/unit/compiler-jpms-test/target/classes</outputDirectory> + <buildDirectory>${basedir}/target/test/unit/compiler-jpms-test/target</buildDirectory> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/src/test/resources/unit/compiler-jpms-test/src/main/java/foo/TestJpms0.java b/src/test/resources/unit/compiler-jpms-test/src/main/java/foo/TestJpms0.java new file mode 100644 index 0000000..2f2110a --- /dev/null +++ b/src/test/resources/unit/compiler-jpms-test/src/main/java/foo/TestJpms0.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package foo; + +public class TestJpms0 +{ + + public TestJpms0() + { + + System.out.println( "Woo Hoo!" ); + } + +} \ No newline at end of file diff --git a/src/test/resources/unit/compiler-jpms-test/src/main/java/module-info.java b/src/test/resources/unit/compiler-jpms-test/src/main/java/module-info.java new file mode 100644 index 0000000..763919e --- /dev/null +++ b/src/test/resources/unit/compiler-jpms-test/src/main/java/module-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +module foo { + // empty +} diff --git a/src/test/resources/unit/compiler-jpms-test/src/test/java/foo/TestJpms0Test.java b/src/test/resources/unit/compiler-jpms-test/src/test/java/foo/TestJpms0Test.java new file mode 100644 index 0000000..6bb7c46 --- /dev/null +++ b/src/test/resources/unit/compiler-jpms-test/src/test/java/foo/TestJpms0Test.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package foo; + +import junit.framework.TestCase; + +public class TestJpms0Test + extends TestCase +{ + public void testJpms0Test() + { + TestJpms0 test = new TestJpms0(); + } +} \ No newline at end of file diff --git a/src/test/resources/unit/compiler-jpms-test/src/test/java/module-info.java b/src/test/resources/unit/compiler-jpms-test/src/test/java/module-info.java new file mode 100644 index 0000000..74985f4 --- /dev/null +++ b/src/test/resources/unit/compiler-jpms-test/src/test/java/module-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +open module foo { + requires junit; +} -- To stop receiving notification emails like this one, please contact s...@apache.org.