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 "requires public"
  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.JavacTask ModuleTestBase
  32  * @run main RequiresPublicTest
  33  */
  34 
  35 import java.nio.file.Files;
  36 import java.nio.file.Path;
  37 
  38 import toolbox.JavacTask;
  39 import toolbox.Task;
  40 import toolbox.ToolBox;
  41 
  42 public class RequiresPublicTest extends ModuleTestBase {
  43 
  44     public static void main(String... args) throws Exception {
  45         RequiresPublicTest t = new RequiresPublicTest();
  46         t.runTests();
  47     }
  48 
  49     @Test
  50     public void testJavaSE_OK(Path base) throws Exception {
  51         Path src = base.resolve("src");
  52         tb.writeJavaFiles(src,
  53                 "module m { requires java.se; }",
  54                 "import java.awt.Frame;\n"  // in java.se
  55                 + "class Test {\n"
  56                 + "    Frame f;\n"
  57                 + "}");
  58         Path classes = base.resolve("classes");
  59         Files.createDirectories(classes);
  60 
  61         new JavacTask(tb, Task.Mode.CMDLINE)
  62                 .files(findJavaFiles(src))
  63                 .outdir(classes)
  64                 .run()
  65                 .writeAll();
  66     }
  67 
  68     @Test
  69     public void testJavaSE_Fail(Path base) throws Exception {
  70         Path src = base.resolve("src");
  71         tb.writeJavaFiles(src,
  72                 "module m { requires java.se; }",
  73                 "import com.sun.source.tree.Tree;\n" // not in java.se (in jdk.compiler)
  74                 + "class Test {\n"
  75                 + "    Tree t;\n"
  76                 + "}");
  77         Path classes = base.resolve("classes");
  78         Files.createDirectories(classes);
  79 
  80         String log = new JavacTask(tb, Task.Mode.CMDLINE)
  81                 .options("-XDrawDiagnostics")
  82                 .files(findJavaFiles(src))
  83                 .outdir(classes)
  84                 .run(Task.Expect.FAIL)
  85                 .writeAll()
  86                 .getOutput(Task.OutputKind.DIRECT);
  87 
  88         if (!log.contains("Test.java:1:27: compiler.err.doesnt.exist: com.sun.source.tree"))
  89             throw new Exception("expected output not found");
  90     }
  91 
  92     @Test
  93     public void testComplex_OK(Path base) throws Exception {
  94         Path src = getComplexSrc(base, "", "");
  95         Path classes = base.resolve("classes");
  96         Files.createDirectories(classes);
  97 
  98         new JavacTask(tb, Task.Mode.CMDLINE)
  99                 .options("--module-source-path", src.toString())
 100                 .files(findJavaFiles(src))
 101                 .outdir(classes)
 102                 .run()
 103                 .writeAll();
 104     }
 105 
 106     @Test
 107     public void testComplex_Fail(Path base) throws Exception {
 108         Path src = getComplexSrc(base,
 109                 "import p5.C5; import p6.C6; import p7.C7;\n",
 110                 "C5 c5; C6 c6; C7 c7;\n");
 111         Path classes = base.resolve("classes");
 112         Files.createDirectories(classes);
 113 
 114         String log = new JavacTask(tb, Task.Mode.CMDLINE)
 115                 .options("-XDrawDiagnostics",
 116                         "--module-source-path", src.toString())
 117                 .files(findJavaFiles(src))
 118                 .outdir(classes)
 119                 .run(Task.Expect.FAIL)
 120                 .writeAll()
 121                 .getOutput(Task.OutputKind.DIRECT);
 122 
 123         String[] expect = {
 124             "C1.java:5:10: compiler.err.not.def.access.package.cant.access: p5.C5, p5",
 125             "C1.java:5:24: compiler.err.not.def.access.package.cant.access: p6.C6, p6",
 126             "C1.java:5:38: compiler.err.not.def.access.package.cant.access: p7.C7, p7",
 127             "C1.java:8:1: compiler.err.cant.resolve.location: kindname.class, C5, , , "
 128                 + "(compiler.misc.location: kindname.class, p1.C1, null)",
 129             "C1.java:8:8: compiler.err.cant.resolve.location: kindname.class, C6, , , "
 130                 + "(compiler.misc.location: kindname.class, p1.C1, null)",
 131             "C1.java:8:15: compiler.err.cant.resolve.location: kindname.class, C7, , , "
 132                 + "(compiler.misc.location: kindname.class, p1.C1, null)"
 133         };
 134 
 135         for (String e: expect) {
 136             if (!log.contains(e))
 137                 throw new Exception("expected output not found: " + e);
 138         }
 139     }
 140 
 141     /*
 142      * Set up the following module graph
 143      *     m1 -> m2 => m3 => m4 -> m5
 144      *              -> m6 => m7
 145      * where -> is requires, => is requires public
 146      */
 147     Path getComplexSrc(Path base, String m1_extraImports, String m1_extraUses) throws Exception {
 148         Path src = base.resolve("src");
 149 
 150         Path src_m1 = src.resolve("m1");
 151         tb.writeJavaFiles(src_m1,
 152                 "module m1 { requires m2; }",
 153                 "package p1;\n"
 154                 + "import p2.C2;\n"
 155                 + "import p3.C3;\n"
 156                 + "import p4.C4;\n"
 157                 + m1_extraImports
 158                 + "class C1 {\n"
 159                 + "  C2 c2; C3 c3; C4 c4;\n"
 160                 + m1_extraUses
 161                 + "}\n");
 162 
 163         Path src_m2 = src.resolve("m2");
 164         tb.writeJavaFiles(src_m2,
 165                 "module m2 {\n"
 166                 + "  requires public m3;\n"
 167                 + "  requires        m6;\n"
 168                 + "  exports p2;\n"
 169                 + "}",
 170                 "package p2;\n"
 171                 + "public class C2 { }\n");
 172 
 173         Path src_m3 = src.resolve("m3");
 174         tb.writeJavaFiles(src_m3,
 175                 "module m3 { requires public m4; exports p3; }",
 176                 "package p3;\n"
 177                 + "public class C3 { }\n");
 178 
 179         Path src_m4 = src.resolve("m4");
 180         tb.writeJavaFiles(src_m4,
 181                 "module m4 { requires m5; exports p4; }",
 182                 "package p4;\n"
 183                 + "public class C4 { }\n");
 184 
 185         Path src_m5 = src.resolve("m5");
 186         tb.writeJavaFiles(src_m5,
 187                 "module m5 { exports p5; }",
 188                 "package p5;\n"
 189                 + "public class C5 { }\n");
 190 
 191         Path src_m6 = src.resolve("m6");
 192         tb.writeJavaFiles(src_m6,
 193                 "module m6 { requires public m7; exports p6; }",
 194                 "package p6;\n"
 195                 + "public class C6 { }\n");
 196 
 197         Path src_m7 = src.resolve("m7");
 198         tb.writeJavaFiles(src_m7,
 199                 "module m7 { exports p7; }",
 200                 "package p7;\n"
 201                 + "public class C7 { }\n");
 202 
 203         return src;
 204     }
 205 }