1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @summary Ensure named modules cannot refer to classpath types.
  27  * @library /tools/lib
  28  * @modules jdk.compiler/com.sun.tools.javac.api
  29  *          jdk.compiler/com.sun.tools.javac.main
  30  * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase
  31  * @run main ModulesAndClassPathTest
  32  */
  33 
  34 import java.io.File;
  35 import java.nio.file.Files;
  36 import java.nio.file.Path;
  37 import java.util.Arrays;
  38 import java.util.List;
  39 import java.util.Set;
  40 
  41 import javax.annotation.processing.AbstractProcessor;
  42 import javax.annotation.processing.RoundEnvironment;
  43 import javax.annotation.processing.SupportedAnnotationTypes;
  44 import javax.lang.model.element.TypeElement;
  45 
  46 import toolbox.JarTask;
  47 import toolbox.JavacTask;
  48 import toolbox.Task;
  49 import toolbox.ToolBox;
  50 
  51 public class ModulesAndClassPathTest extends ModuleTestBase {
  52 
  53     public static void main(String... args) throws Exception {
  54         new ModulesAndClassPathTest().runTests();
  55     }
  56 
  57     @Test
  58     public void testModulesAndClassPath(Path base) throws Exception {
  59         Path jar = prepareTestJar(base);
  60 
  61         Path moduleSrc = base.resolve("module-src");
  62         Path m1 = moduleSrc.resolve("m1");
  63 
  64         Path classes = base.resolve("classes");
  65 
  66         Files.createDirectories(classes);
  67 
  68         tb.writeJavaFiles(m1,
  69                           "module m1 { }",
  70                           "package impl; public class Impl { api.Api api; }");
  71 
  72         List<String> modLog = new JavacTask(tb)
  73                                 .options("-classpath", jar.toString(),
  74                                          "-XDrawDiagnostics")
  75                                 .outdir(classes)
  76                                 .files(findJavaFiles(moduleSrc))
  77                                 .run(Task.Expect.FAIL)
  78                                 .writeAll()
  79                                 .getOutputLines(Task.OutputKind.DIRECT);
  80 
  81         List<String> expected = Arrays.asList("Impl.java:1:38: compiler.err.doesnt.exist: api",
  82                                               "1 error");
  83 
  84         if (!expected.equals(modLog)) {
  85             throw new Exception("unexpected output: " + modLog);
  86         }
  87 
  88         new JavacTask(tb)
  89           .options("-classpath", jar.toString(),
  90                    "-XaddReads:m1=ALL-UNNAMED")
  91           .outdir(classes)
  92           .files(findJavaFiles(moduleSrc))
  93           .run()
  94           .writeAll()
  95           .getOutputLines(Task.OutputKind.DIRECT);
  96 
  97         new JavacTask(tb)
  98           .options("-classpath", jar.toString() + File.pathSeparator + System.getProperty("test.classes"),
  99                    "-XaddReads:m1=ALL-UNNAMED",
 100                    "-processor", ProcessorImpl.class.getName())
 101           .outdir(classes)
 102           .files(findJavaFiles(moduleSrc))
 103           .run()
 104           .writeAll()
 105           .getOutputLines(Task.OutputKind.DIRECT);
 106     }
 107 
 108     @Test
 109     public void testImplicitSourcePathModuleInfo(Path base) throws Exception {
 110         Path jar = prepareTestJar(base);
 111 
 112         Path moduleSrc = base.resolve("module-src");
 113         Path m1 = moduleSrc.resolve("m1");
 114 
 115         Path classes = base.resolve("classes");
 116 
 117         Files.createDirectories(classes);
 118 
 119         tb.writeJavaFiles(m1,
 120                           "module m1 { }",
 121                           "package impl; public class Impl { api.Api api; }");
 122 
 123         List<String> modLog = new JavacTask(tb)
 124                                 .options("-classpath", jar.toString(),
 125                                          "-sourcepath", m1.toString(),
 126                                          "-XDrawDiagnostics")
 127                                 .outdir(classes)
 128                                 .files(m1.resolve("impl").resolve("Impl.java"))
 129                                 .run(Task.Expect.FAIL)
 130                                 .writeAll()
 131                                 .getOutputLines(Task.OutputKind.DIRECT);
 132 
 133         List<String> expected = Arrays.asList("Impl.java:1:38: compiler.err.doesnt.exist: api",
 134                                               "1 error");
 135 
 136         if (!expected.equals(modLog)) {
 137             throw new Exception("unexpected output: " + modLog);
 138         }
 139     }
 140 
 141     @Test
 142     public void testModuleInfoFromOutput(Path base) throws Exception {
 143         Path jar = prepareTestJar(base);
 144 
 145         Path moduleSrc = base.resolve("module-src");
 146         Path m1 = moduleSrc.resolve("m1");
 147 
 148         Path classes = base.resolve("classes");
 149 
 150         Files.createDirectories(classes);
 151 
 152         tb.writeJavaFiles(m1,
 153                           "module m1 { }",
 154                           "package impl; public class Impl { api.Api api; }");
 155 
 156         new JavacTask(tb)
 157           .options("-classpath", jar.toString(),
 158                    "-XDrawDiagnostics")
 159           .outdir(classes)
 160           .files(m1.resolve("module-info.java"))
 161           .run()
 162           .writeAll()
 163           .getOutputLines(Task.OutputKind.DIRECT);
 164 
 165         List<String> modLog = new JavacTask(tb)
 166                                 .options("-classpath", jar.toString(),
 167                                          "-XDrawDiagnostics")
 168                                 .outdir(classes)
 169                                 .files(m1.resolve("impl").resolve("Impl.java"))
 170                                 .run(Task.Expect.FAIL)
 171                                 .writeAll()
 172                                 .getOutputLines(Task.OutputKind.DIRECT);
 173 
 174         List<String> expected = Arrays.asList("Impl.java:1:38: compiler.err.doesnt.exist: api",
 175                                               "1 error");
 176 
 177         if (!expected.equals(modLog)) {
 178             throw new Exception("unexpected output: " + modLog);
 179         }
 180     }
 181 
 182     private Path prepareTestJar(Path base) throws Exception {
 183         Path legacySrc = base.resolve("legacy-src");
 184         tb.writeJavaFiles(legacySrc,
 185                           "package api; public abstract class Api {}");
 186         Path legacyClasses = base.resolve("legacy-classes");
 187         Files.createDirectories(legacyClasses);
 188 
 189         String log = new JavacTask(tb)
 190                 .options()
 191                 .outdir(legacyClasses)
 192                 .files(findJavaFiles(legacySrc))
 193                 .run()
 194                 .writeAll()
 195                 .getOutput(Task.OutputKind.DIRECT);
 196 
 197         if (!log.isEmpty()) {
 198             throw new Exception("unexpected output: " + log);
 199         }
 200 
 201         Path lib = base.resolve("lib");
 202 
 203         Files.createDirectories(lib);
 204 
 205         Path jar = lib.resolve("test-api-1.0.jar");
 206 
 207         new JarTask(tb, jar)
 208           .baseDir(legacyClasses)
 209           .files("api/Api.class")
 210           .run();
 211 
 212         return jar;
 213     }
 214 
 215     @SupportedAnnotationTypes("*")
 216     public static class ProcessorImpl extends AbstractProcessor {
 217         @Override
 218         public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
 219             return false;
 220         }
 221     }
 222 
 223     @Test
 224     public void testClassOutputVisibleForIncrementalCompilation(Path base) throws Exception {
 225         Path moduleSrc = base.resolve("module-src");
 226         Path m1 = moduleSrc.resolve("m1");
 227 
 228         Path classes = base.resolve("classes");
 229 
 230         Files.createDirectories(classes);
 231 
 232         tb.writeJavaFiles(m1,
 233                           "module m1 { exports impl; }",
 234                           "package impl; public class Impl { }",
 235                           "package src; public class Src { }",
 236                           "package test; public class TestCP extends impl.Impl { }",
 237                           "package test; public class TestSP extends src.Src { }");
 238 
 239         new JavacTask(tb)
 240           .outdir(classes)
 241           .files(m1.resolve("impl").resolve("Impl.java"))
 242           .run()
 243           .writeAll()
 244           .getOutputLines(Task.OutputKind.DIRECT);
 245 
 246         new JavacTask(tb)
 247           .outdir(classes)
 248           .files(m1.resolve("module-info.java"))
 249           .run()
 250           .writeAll()
 251           .getOutputLines(Task.OutputKind.DIRECT);
 252 
 253         new JavacTask(tb)
 254           .outdir(classes)
 255           .files(m1.resolve("test").resolve("TestCP.java"))
 256           .run()
 257           .writeAll()
 258           .getOutputLines(Task.OutputKind.DIRECT);
 259 
 260         new JavacTask(tb)
 261           .options("-sourcepath", m1.toString())
 262           .outdir(classes)
 263           .files(m1.resolve("test").resolve("TestSP.java"))
 264           .run()
 265           .writeAll()
 266           .getOutputLines(Task.OutputKind.DIRECT);
 267     }
 268 }