1 /*
   2  * Copyright (c) 2015, 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 tests for --module-path
  27  * @library /tools/lib
  28  * @modules
  29  *      jdk.compiler/com.sun.tools.javac.api
  30  *      jdk.compiler/com.sun.tools.javac.main
  31  *      jdk.jdeps/com.sun.tools.javap
  32  *      jdk.jlink
  33  * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder
  34  *      ModuleTestBase
  35  * @run main ModulePathTest
  36  */
  37 
  38 import java.io.File;
  39 import java.io.IOException;
  40 import java.nio.file.Files;
  41 import java.nio.file.Path;
  42 import java.util.spi.ToolProvider;
  43 
  44 import toolbox.JarTask;
  45 import toolbox.JavacTask;
  46 import toolbox.ModuleBuilder;
  47 import toolbox.Task;
  48 import toolbox.ToolBox;
  49 
  50 public class ModulePathTest extends ModuleTestBase {
  51 
  52     public static final String PATH_SEP = File.pathSeparator;
  53 
  54     public static void main(String... args) throws Exception {
  55         ModulePathTest t = new ModulePathTest();
  56         t.runTests();
  57     }
  58 
  59     @Test
  60     public void testNotExistsOnPath(Path base) throws Exception {
  61         Path src = base.resolve("src");
  62         tb.writeJavaFiles(src, "class C { }");
  63 
  64         String log = new JavacTask(tb, Task.Mode.CMDLINE)
  65                 .options("-XDrawDiagnostics",
  66                         "--module-path", "doesNotExist")
  67                 .files(findJavaFiles(src))
  68                 .run(Task.Expect.FAIL)
  69                 .writeAll()
  70                 .getOutput(Task.OutputKind.DIRECT);
  71 
  72         if (!log.contains("- compiler.err.illegal.argument.for.option: --module-path, doesNotExist"))
  73             throw new Exception("expected output not found");
  74     }
  75 
  76     @Test
  77     public void testNotADirOnPath_1(Path base) throws Exception {
  78         Path src = base.resolve("src");
  79         tb.writeJavaFiles(src, "class C { }");
  80         tb.writeFile("dummy.txt", "");
  81 
  82         String log = new JavacTask(tb, Task.Mode.CMDLINE)
  83                 .options("-XDrawDiagnostics",
  84                         "--module-path", "dummy.txt")
  85                 .files(findJavaFiles(src))
  86                 .run(Task.Expect.FAIL)
  87                 .writeAll()
  88                 .getOutput(Task.OutputKind.DIRECT);
  89 
  90         if (!log.contains("- compiler.err.illegal.argument.for.option: --module-path, dummy.txt"))
  91             throw new Exception("expected output not found");
  92     }
  93 
  94     @Test
  95     public void testNotADirOnPath_2(Path base) throws Exception {
  96         Path src = base.resolve("src");
  97         tb.writeJavaFiles(src, "class C { }");
  98         tb.writeFile("dummy.jimage", "");
  99 
 100         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 101                 .options("-XDrawDiagnostics",
 102                         "--module-path", "dummy.jimage")
 103                 .files(findJavaFiles(src))
 104                 .run(Task.Expect.FAIL)
 105                 .writeAll()
 106                 .getOutput(Task.OutputKind.DIRECT);
 107 
 108         if (!log.contains("- compiler.err.illegal.argument.for.option: --module-path, dummy.jimage"))
 109             throw new Exception("expected output not found");
 110     }
 111 
 112     @Test
 113     public void testExplodedModuleOnPath(Path base) throws Exception {
 114         Path modSrc = base.resolve("modSrc");
 115         tb.writeJavaFiles(modSrc,
 116                 "module m1 { exports p; }",
 117                 "package p; public class CC { }");
 118         Path modClasses = base.resolve("modClasses");
 119         Files.createDirectories(modClasses);
 120 
 121         new JavacTask(tb, Task.Mode.CMDLINE)
 122                 .outdir(modClasses)
 123                 .files(findJavaFiles(modSrc))
 124                 .run()
 125                 .writeAll();
 126 
 127         Path src = base.resolve("src");
 128         tb.writeJavaFiles(src,
 129                 "module m { requires m1 ; }",
 130                 "class C { }");
 131         Path classes = base.resolve("classes");
 132         Files.createDirectories(classes);
 133 
 134         new JavacTask(tb, Task.Mode.CMDLINE)
 135                 .outdir(classes)
 136                 .options("--module-path", modClasses.toString())
 137                 .files(findJavaFiles(src))
 138                 .run()
 139                 .writeAll();
 140     }
 141 
 142     @Test
 143     public void testBadExplodedModuleOnPath(Path base) throws Exception {
 144         Path modClasses = base.resolve("modClasses");
 145         tb.writeFile(modClasses.resolve("module-info.class"), "module m1 { }");
 146 
 147         Path src = base.resolve("src");
 148         tb.writeJavaFiles(src,
 149                 "module m { requires m1 ; }",
 150                 "class C { }");
 151         Path classes = base.resolve("classes");
 152         Files.createDirectories(classes);
 153 
 154         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 155                 .outdir(classes)
 156                 .options("-XDrawDiagnostics",
 157                         "--module-path", modClasses.toString())
 158                 .files(findJavaFiles(src))
 159                 .run(Task.Expect.FAIL)
 160                 .writeAll()
 161                 .getOutput(Task.OutputKind.DIRECT);
 162 
 163         if (!log.contains("- compiler.err.locn.bad.module-info: " + modClasses.toString()))
 164             throw new Exception("expected output not found");
 165     }
 166 
 167     @Test
 168     public void testAutoJarOnPath(Path base) throws Exception {
 169         Path jarSrc = base.resolve("jarSrc");
 170         tb.writeJavaFiles(jarSrc,
 171                 "package p; public class CC { }");
 172         Path jarClasses = base.resolve("jarClasses");
 173         Files.createDirectories(jarClasses);
 174 
 175         new JavacTask(tb, Task.Mode.CMDLINE)
 176                 .outdir(jarClasses)
 177                 .files(findJavaFiles(jarSrc))
 178                 .run()
 179                 .writeAll();
 180 
 181         Path moduleJar = base.resolve("m1.jar");
 182         new JarTask(tb, moduleJar)
 183           .baseDir(jarClasses)
 184           .files("p/CC.class")
 185           .run();
 186 
 187         Path src = base.resolve("src");
 188         tb.writeJavaFiles(src, "class C { p.CC cc; }");
 189         Path classes = base.resolve("classes");
 190         Files.createDirectories(classes);
 191 
 192         new JavacTask(tb, Task.Mode.CMDLINE)
 193                 .outdir(classes)
 194                 .options("--module-path", moduleJar.toString(), "--add-modules", "m1")
 195                 .files(findJavaFiles(src))
 196                 .run()
 197                 .writeAll();
 198     }
 199 
 200     @Test
 201     public void testModJarOnPath(Path base) throws Exception {
 202         Path jarSrc = base.resolve("jarSrc");
 203         tb.writeJavaFiles(jarSrc,
 204                 "module m1 { exports p; }",
 205                 "package p; public class CC { }");
 206         Path jarClasses = base.resolve("jarClasses");
 207         Files.createDirectories(jarClasses);
 208 
 209         new JavacTask(tb, Task.Mode.CMDLINE)
 210                 .outdir(jarClasses)
 211                 .files(findJavaFiles(jarSrc))
 212                 .run()
 213                 .writeAll();
 214 
 215         Path moduleJar = base.resolve("myModule.jar"); // deliberately not m1
 216         new JarTask(tb, moduleJar)
 217           .baseDir(jarClasses)
 218           .files("module-info.class", "p/CC.class")
 219           .run();
 220 
 221         Path src = base.resolve("src");
 222         tb.writeJavaFiles(src,
 223                 "module m { requires m1 ; }",
 224                 "class C { }");
 225         Path classes = base.resolve("classes");
 226         Files.createDirectories(classes);
 227 
 228         new JavacTask(tb, Task.Mode.CMDLINE)
 229                 .outdir(classes)
 230                 .options("--module-path", moduleJar.toString())
 231                 .files(findJavaFiles(src))
 232                 .run()
 233                 .writeAll();
 234     }
 235 
 236     @Test
 237     public void testBadJarOnPath(Path base) throws Exception {
 238         Path src = base.resolve("src");
 239         tb.writeJavaFiles(src, "class C { }");
 240         tb.writeFile("dummy.jar", "");
 241 
 242         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 243                 .options("-XDrawDiagnostics",
 244                         "--module-path", "dummy.jar")
 245                 .files(findJavaFiles(src))
 246                 .run(Task.Expect.FAIL)
 247                 .writeAll()
 248                 .getOutput(Task.OutputKind.DIRECT);
 249 
 250         if (!log.contains("- compiler.err.locn.cant.read.file: dummy.jar"))
 251             throw new Exception("expected output not found");
 252     }
 253 
 254     @Test
 255     public void testJModOnPath(Path base) throws Exception {
 256         Path jmodSrc = base.resolve("jmodSrc");
 257         tb.writeJavaFiles(jmodSrc,
 258                 "module m1 { exports p; }",
 259                 "package p; public class CC { }");
 260         Path jmodClasses = base.resolve("jmodClasses");
 261         Files.createDirectories(jmodClasses);
 262 
 263         new JavacTask(tb, Task.Mode.CMDLINE)
 264                 .outdir(jmodClasses)
 265                 .files(findJavaFiles(jmodSrc))
 266                 .run()
 267                 .writeAll();
 268 
 269         Path jmod = base.resolve("myModule.jmod"); // deliberately not m1
 270         jmod(jmodClasses, jmod);
 271 
 272         Path src = base.resolve("src");
 273         tb.writeJavaFiles(src,
 274                 "module m { requires m1 ; }",
 275                 "class C { }");
 276         Path classes = base.resolve("classes");
 277         Files.createDirectories(classes);
 278 
 279         new JavacTask(tb, Task.Mode.CMDLINE)
 280                 .outdir(classes)
 281                 .options("--module-path", jmod.toString())
 282                 .files(findJavaFiles(src))
 283                 .run()
 284                 .writeAll();
 285     }
 286 
 287     @Test
 288     public void testBadJModOnPath(Path base) throws Exception {
 289         Path src = base.resolve("src");
 290         tb.writeJavaFiles(src, "class C { }");
 291         tb.writeFile("dummy.jmod", "");
 292 
 293         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 294                 .options("-XDrawDiagnostics",
 295                         "--module-path", "dummy.jmod")
 296                 .files(findJavaFiles(src))
 297                 .run(Task.Expect.FAIL)
 298                 .writeAll()
 299                 .getOutput(Task.OutputKind.DIRECT);
 300 
 301         if (!log.contains("- compiler.err.locn.cant.read.file: dummy.jmod"))
 302             throw new Exception("expected output not found");
 303     }
 304 
 305     @Test
 306     public void relativePath(Path base) throws Exception {
 307         Path modules = base.resolve("modules");
 308         new ModuleBuilder(tb, "m1").build(modules);
 309 
 310         Path src = base.resolve("src");
 311         tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
 312 
 313         new JavacTask(tb, Task.Mode.CMDLINE)
 314                 .options("-XDrawDiagnostics",
 315                         "--module-path", modules + "/./../modules")
 316                 .files(findJavaFiles(src))
 317                 .run()
 318                 .writeAll();
 319     }
 320 
 321     @Test
 322     public void duplicatePaths_1(Path base) throws Exception {
 323         Path modules = base.resolve("modules");
 324         new ModuleBuilder(tb, "m1").build(modules);
 325 
 326         Path src = base.resolve("src");
 327         tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
 328 
 329         new JavacTask(tb, Task.Mode.CMDLINE)
 330                 .options("-XDrawDiagnostics",
 331                         "--module-path", modules + "/./../modules" + PATH_SEP + modules)
 332                 .files(findJavaFiles(src))
 333                 .run()
 334                 .writeAll();
 335     }
 336 
 337     @Test
 338     public void duplicatePaths_2(Path base) throws Exception {
 339         Path modules = base.resolve("modules");
 340         new ModuleBuilder(tb, "m1").build(modules);
 341 
 342         Path src = base.resolve("src");
 343         tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
 344 
 345         new JavacTask(tb, Task.Mode.CMDLINE)
 346                 .options("-XDrawDiagnostics",
 347                         "--module-path", modules.toString(),
 348                         "--module-path", modules.toString())
 349                 .files(findJavaFiles(src))
 350                 .run()
 351                 .writeAll();
 352     }
 353 
 354     @Test
 355     public void oneModuleHidesAnother(Path base) throws Exception {
 356         Path modules = base.resolve("modules");
 357         new ModuleBuilder(tb, "m1")
 358                 .exports("pkg1")
 359                 .classes("package pkg1; public class E { }")
 360                 .build(modules);
 361 
 362         Path deepModuleDirSrc = base.resolve("deepModuleDirSrc");
 363         Path deepModuleDir = modules.resolve("deepModuleDir");
 364         new ModuleBuilder(tb, "m1")
 365                 .exports("pkg2")
 366                 .classes("package pkg2; public class E { }")
 367                 .build(deepModuleDirSrc, deepModuleDir);
 368 
 369         Path src = base.resolve("src");
 370         tb.writeJavaFiles(src, "module m2 { requires m1; }", " package p; class A { void main() { pkg2.E.class.getName(); } }");
 371 
 372         new JavacTask(tb, Task.Mode.CMDLINE)
 373                 .options("-XDrawDiagnostics",
 374                         "--module-path", deepModuleDir + PATH_SEP + modules)
 375                 .files(findJavaFiles(src))
 376                 .run()
 377                 .writeAll();
 378     }
 379 
 380     @Test
 381     public void modulesInDifferentContainers(Path base) throws Exception {
 382         Path modules = base.resolve("modules");
 383         new ModuleBuilder(tb, "m1")
 384                 .exports("one")
 385                 .classes("package one; public class A { }")
 386                 .build(modules);
 387 
 388         new ModuleBuilder(tb, "m2")
 389                 .requires("m1", modules)
 390                 .build(base.resolve("tmp"));
 391         jar(base.resolve("tmp/m2"), modules.resolve("m2.jar"));
 392 
 393         new ModuleBuilder(tb, "m3")
 394                 .requires("m2", modules)
 395                 .build(base.resolve("tmp"));
 396         jmod(base.resolve("tmp/m3"), modules.resolve("m3.jmod"));
 397 
 398         Path src = base.resolve("src");
 399         tb.writeJavaFiles(src, "module m { requires m3; requires m2; requires m1; }",
 400                 "package p; class A { void main() { one.A.class.getName(); } }");
 401 
 402         new JavacTask(tb, Task.Mode.CMDLINE)
 403                 .options("-XDrawDiagnostics",
 404                         "--module-path", modules.toString())
 405                 .files(findJavaFiles(src))
 406                 .run()
 407                 .writeAll();
 408     }
 409 
 410     private void jar(Path dir, Path jar) throws IOException {
 411         new JarTask(tb, jar)
 412                 .baseDir(dir)
 413                 .files(".")
 414                 .run()
 415                 .writeAll();
 416     }
 417 
 418     private void jmod(Path dir, Path jmod) throws Exception {
 419         String[] args = {
 420                 "create",
 421                 "--class-path", dir.toString(),
 422                 jmod.toString()
 423         };
 424         ToolProvider jmodTool = ToolProvider.findFirst("jmod").orElseThrow(() ->
 425                 new RuntimeException("jmod tool not found")
 426         );
 427         jmodTool.run(System.out, System.out, args);
 428     }
 429 }