You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by so...@apache.org on 2018/05/12 10:08:20 UTC

[maven-compiler-plugin] 01/01: Introduce white-box testing modules

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 <so...@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
sor@apache.org.