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 graph resolution issues
  27  * @library /tools/lib
  28  * @modules
  29  *      jdk.compiler/com.sun.tools.javac.api
  30  *      jdk.compiler/com.sun.tools.javac.main
  31  * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder
  32  *      ModuleTestBase
  33  * @run main GraphsTest
  34  */
  35 
  36 import java.io.File;
  37 import java.nio.file.Files;
  38 import java.nio.file.Path;
  39 import java.util.Arrays;
  40 import java.util.List;
  41 import java.util.regex.Pattern;
  42 
  43 import toolbox.JarTask;
  44 import toolbox.JavacTask;
  45 import toolbox.ModuleBuilder;
  46 import toolbox.Task;
  47 import toolbox.ToolBox;
  48 
  49 public class GraphsTest extends ModuleTestBase {
  50 
  51     public static void main(String... args) throws Exception {
  52         GraphsTest t = new GraphsTest();
  53         t.runTests();
  54     }
  55 
  56     /**
  57      * Tests diamond graph with an automatic module added in.
  58      * +-------------+          +--------------------+         +------------------+
  59      * | module M    |          | module N           |         | module O         |
  60      * |             | ----->   |                    | --->    |                  |  --> J.jar
  61      * | require N   |          | requires public  O |         |                  |
  62      * | require L   |          |                    |         +------------------+
  63      * +-------------+          +--------------------+                  ^
  64      *       |                                                          |
  65      *       |                  +--------------------+                  |
  66      *       ------------------>| module L           |                  |
  67      *                          |                    |------------------
  68      *                          | requires public O  |
  69      *                          |                    |
  70      *                          +--------------------+
  71      *
  72      */
  73     @Test
  74     public void diamond(Path base) throws Exception {
  75 
  76         Path modSrc = Files.createDirectories(base.resolve("modSrc"));
  77         Path modules = Files.createDirectories(base.resolve("modules"));
  78 
  79         new ModuleBuilder(tb, "J")
  80                 .exports("openJ")
  81                 .classes("package openJ; public class J { }")
  82                 .classes("package closedJ; public class J { }")
  83                 .build(base.resolve("jar"));
  84 
  85         Path jarModules = Files.createDirectories(base.resolve("jarModules"));
  86         Path jar = jarModules.resolve("J.jar");
  87         new JarTask(tb, jar)
  88                 .baseDir(base.resolve("jar/J"))
  89                 .files(".")
  90                 .run()
  91                 .writeAll();
  92 
  93         new ModuleBuilder(tb, "O")
  94                 .exports("openO")
  95                 .requiresPublic("J", jarModules)
  96                 .classes("package openO; public class O { openJ.J j; }")
  97                 .classes("package closedO; public class O { }")
  98                 .build(modSrc, modules);
  99         new ModuleBuilder(tb, "N")
 100                 .requiresPublic("O", modules, jarModules)
 101                 .exports("openN")
 102                 .classes("package openN; public class N { }")
 103                 .classes("package closedN; public class N { }")
 104                 .build(modSrc, modules);
 105         new ModuleBuilder(tb, "L")
 106                 .requiresPublic("O", modules, jarModules)
 107                 .exports("openL")
 108                 .classes("package openL; public class L { }")
 109                 .classes("package closedL; public class L { }")
 110                 .build(modSrc, modules);
 111         ModuleBuilder m = new ModuleBuilder(tb, "M");
 112         //positive case
 113         Path positiveSrc = m
 114                 .requires("N", modules)
 115                 .requires("L", modules)
 116                 .classes("package p; public class Positive { openO.O o; openN.N n; openL.L l; }")
 117                 .write(base.resolve("positiveSrc"));
 118 
 119         new JavacTask(tb)
 120                 .options("-XDrawDiagnostics", "-p", modules + File.pathSeparator + jarModules)
 121                 .outdir(Files.createDirectories(base.resolve("positive")))
 122                 .files(findJavaFiles(positiveSrc))
 123                 .run()
 124                 .writeAll();
 125         //negative case
 126         Path negativeSrc = m.classes("package p; public class Negative { closedO.O o; closedN.N n; closedL.L l; }")
 127                 .write(base.resolve("negativeSrc"));
 128         List<String> log = new JavacTask(tb)
 129                 .options("-XDrawDiagnostics", "-p", modules + File.pathSeparator + jarModules)
 130                 .outdir(Files.createDirectories(base.resolve("negative")))
 131                 .files(findJavaFiles(negativeSrc))
 132                 .run(Task.Expect.FAIL)
 133                 .writeAll()
 134                 .getOutputLines(Task.OutputKind.DIRECT);
 135 
 136         List<String> expected = Arrays.asList(
 137                 "Negative.java:1:43: compiler.err.doesnt.exist: closedO",
 138                 "Negative.java:1:56: compiler.err.doesnt.exist: closedN",
 139                 "Negative.java:1:69: compiler.err.doesnt.exist: closedL");
 140         if (!log.containsAll(expected)) {
 141             throw new Exception("Expected output not found");
 142         }
 143         //multi module mode
 144         m.write(modSrc);
 145         List<String> out = new JavacTask(tb)
 146                 .options("-XDrawDiagnostics",
 147                         "--module-source-path", modSrc.toString(),
 148                         "-p", jarModules.toString()
 149                 )
 150                 .outdir(Files.createDirectories(base.resolve("negative")))
 151                 .files(findJavaFiles(modSrc))
 152                 .run(Task.Expect.FAIL)
 153                 .writeAll()
 154                 .getOutputLines(Task.OutputKind.DIRECT);
 155         expected = Arrays.asList(
 156                 "Negative.java:1:43: compiler.err.not.def.access.package.cant.access: closedO.O, closedO",
 157                 "Negative.java:1:56: compiler.err.not.def.access.package.cant.access: closedN.N, closedN",
 158                 "Negative.java:1:69: compiler.err.not.def.access.package.cant.access: closedL.L, closedL");
 159         if (!out.containsAll(expected)) {
 160             throw new Exception("Expected output not found");
 161         }
 162         //checks if the output does not contain messages about exported packages.
 163         Pattern regex = Pattern.compile("compiler\\.err.*(openO\\.O|openN\\.N|openL\\.L)");
 164         for (String s : out) {
 165             if (regex.matcher(s).find()) {
 166                 throw new Exception("Unexpected output: " + s);
 167             }
 168         }
 169     }
 170 
 171     /**
 172      * Tests graph where module M reexport package of N, but N export the package only to M.
 173      *
 174     +-------------+        +--------------------+        +---------------+
 175     | module L    |        | module M           |        | module N      |
 176     |             | -----> |                    | -----> |               |
 177     |  requires M |        |  requires public N |        | exports P to M|
 178     +-------------+        |                    |        +---------------+
 179                            +--------------------+
 180     */
 181     @Test
 182     public void reexportOfQualifiedExport(Path base) throws Exception {
 183         Path modSrc = base.resolve("modSrc");
 184         new ModuleBuilder(tb, "M")
 185                 .requiresPublic("N")
 186                 .write(modSrc);
 187         new ModuleBuilder(tb, "N")
 188                 .exportsTo("pack", "M")
 189                 .classes("package pack; public class Clazz { }")
 190                 .write(modSrc);
 191         new ModuleBuilder(tb, "L")
 192                 .requires("M")
 193                 .classes("package p; public class A { A(pack.Clazz cl){} } ")
 194                 .write(modSrc);
 195         String log = new JavacTask(tb)
 196                 .options("-XDrawDiagnostics",
 197                         "-modulesourcepath", modSrc.toString())
 198                 .outdir(Files.createDirectories(base.resolve("negative")))
 199                 .files(findJavaFiles(modSrc))
 200                 .run(Task.Expect.FAIL)
 201                 .writeAll()
 202                 .getOutput(Task.OutputKind.DIRECT);
 203 
 204         String expected = "A.java:1:35: compiler.err.not.def.access.package.cant.access: pack.Clazz, pack";
 205         if (!log.contains(expected)) {
 206             throw new Exception("Expected output not found");
 207         }
 208     }
 209 }