RequiresStaticTest.java revision 3792:d516975e8110
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 * @bug 8161906 8161596
27 * @summary tests for "requires static"
28 * @library /tools/lib
29 * @modules
30 *      jdk.compiler/com.sun.tools.javac.api
31 *      jdk.compiler/com.sun.tools.javac.main
32 * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
33 * @run main RequiresStaticTest
34 */
35
36import java.io.File;
37import java.nio.file.Files;
38import java.nio.file.Path;
39
40import toolbox.JavaTask;
41import toolbox.JavacTask;
42import toolbox.Task;
43import toolbox.Task.OutputKind;
44
45public class RequiresStaticTest extends ModuleTestBase {
46
47    public static void main(String... args) throws Exception {
48        RequiresStaticTest t = new RequiresStaticTest();
49        t.runTests();
50    }
51
52    @Test
53    public void testJavaSE_OK(Path base) throws Exception {
54        Path src = base.resolve("src");
55        tb.writeJavaFiles(src,
56                "module m { requires static java.se; }",
57                "import java.awt.Frame;\n"  // in java.se
58                + "class Test {\n"
59                + "    Frame f;\n"
60                + "}");
61        Path classes = base.resolve("classes");
62        Files.createDirectories(classes);
63
64        new JavacTask(tb, Task.Mode.CMDLINE)
65                .files(findJavaFiles(src))
66                .outdir(classes)
67                .run()
68                .writeAll();
69    }
70
71    @Test
72    public void testJavaSE_Fail(Path base) throws Exception {
73        Path src = base.resolve("src");
74        tb.writeJavaFiles(src,
75                "module m { requires static java.se; }",
76                "import com.sun.source.tree.Tree;\n" // not in java.se (in jdk.compiler)
77                + "class Test {\n"
78                + "    Tree t;\n"
79                + "}");
80        Path classes = base.resolve("classes");
81        Files.createDirectories(classes);
82
83        String log = new JavacTask(tb, Task.Mode.CMDLINE)
84                .options("-XDrawDiagnostics")
85                .files(findJavaFiles(src))
86                .outdir(classes)
87                .run(Task.Expect.FAIL)
88                .writeAll()
89                .getOutput(Task.OutputKind.DIRECT);
90
91        if (!log.contains("Test.java:1:27: compiler.err.doesnt.exist: com.sun.source.tree"))
92            throw new Exception("expected output not found");
93    }
94
95    @Test
96    public void testComplex_OK(Path base) throws Exception {
97        Path src = getComplexSrc(base, "", "");
98        Path classes = base.resolve("classes");
99        Files.createDirectories(classes);
100
101        new JavacTask(tb, Task.Mode.CMDLINE)
102                .options("--module-source-path", src.toString())
103                .files(findJavaFiles(src))
104                .outdir(classes)
105                .run()
106                .writeAll();
107    }
108
109    @Test
110    public void testComplex_Fail(Path base) throws Exception {
111        Path src = getComplexSrc(base,
112                "import p5.C5; import p6.C6; import p7.C7; import p8.C8;\n",
113                "C5 c5; C6 c6; C7 c7; C8 c8;\n");
114        Path classes = base.resolve("classes");
115        Files.createDirectories(classes);
116
117        String log = new JavacTask(tb, Task.Mode.CMDLINE)
118                .options("-XDrawDiagnostics",
119                        "--module-source-path", src.toString())
120                .files(findJavaFiles(src))
121                .outdir(classes)
122                .run(Task.Expect.FAIL)
123                .writeAll()
124                .getOutput(Task.OutputKind.DIRECT);
125
126        String[] expect = {
127            "C1.java:5:10: compiler.err.not.def.access.package.cant.access: p5.C5, p5",
128            "C1.java:5:24: compiler.err.not.def.access.package.cant.access: p6.C6, p6",
129            "C1.java:5:38: compiler.err.not.def.access.package.cant.access: p7.C7, p7",
130            "C1.java:5:52: compiler.err.not.def.access.package.cant.access: p8.C8, p8",
131            "C1.java:8:1: compiler.err.cant.resolve.location: kindname.class, C5, , , "
132                + "(compiler.misc.location: kindname.class, p1.C1, null)",
133            "C1.java:8:8: compiler.err.cant.resolve.location: kindname.class, C6, , , "
134                + "(compiler.misc.location: kindname.class, p1.C1, null)",
135            "C1.java:8:15: compiler.err.cant.resolve.location: kindname.class, C7, , , "
136                + "(compiler.misc.location: kindname.class, p1.C1, null)",
137            "C1.java:8:22: compiler.err.cant.resolve.location: kindname.class, C8, , , "
138                + "(compiler.misc.location: kindname.class, p1.C1, null)"
139        };
140
141        for (String e: expect) {
142            if (!log.contains(e))
143                throw new Exception("expected output not found: " + e);
144        }
145    }
146
147    /*
148     * Set up the following module graph
149     *     m1 -> m2 => m3 -=-> m4 --> m5
150     *            \           /
151     *              \       /
152     *                v   v
153     *                  m6 => m7 --> m8
154     * where -> is requires, => is requires transitive, --> is requires static, -=-> is requires transitive static
155     */
156    Path getComplexSrc(Path base, String m1_extraImports, String m1_extraUses) throws Exception {
157        Path src = base.resolve("src");
158
159        Path src_m1 = src.resolve("m1");
160        tb.writeJavaFiles(src_m1,
161                "module m1 { requires m2; }",
162                "package p1;\n"
163                + "import p2.C2;\n"
164                + "import p3.C3;\n"
165                + "import p4.C4;\n"
166                + m1_extraImports
167                + "class C1 {\n"
168                + "  C2 c2; C3 c3; C4 c4;\n"
169                + m1_extraUses
170                + "}\n");
171
172        Path src_m2 = src.resolve("m2");
173        tb.writeJavaFiles(src_m2,
174                "module m2 {\n"
175                + "  requires transitive m3;\n"
176                + "  requires static m6;\n"
177                + "  exports p2;\n"
178                + "}",
179                "package p2;\n"
180                + "public class C2 {p7.C7 c7; p6.C6 c6; p4.C4 c4;}\n");
181
182        Path src_m3 = src.resolve("m3");
183        tb.writeJavaFiles(src_m3,
184                "module m3 { requires transitive static m4; exports p3; }",
185                "package p3;\n"
186                + "public class C3 { }\n");
187
188        Path src_m4 = src.resolve("m4");
189        tb.writeJavaFiles(src_m4,
190                "module m4 { requires m5; requires static m6; exports p4; }",
191                "package p4;\n"
192                + "public class C4 { p6.C6 c6; p7.C7 c7;}\n");
193
194        Path src_m5 = src.resolve("m5");
195        tb.writeJavaFiles(src_m5,
196                "module m5 { exports p5; }",
197                "package p5;\n"
198                + "public class C5 { }\n");
199
200        Path src_m6 = src.resolve("m6");
201        tb.writeJavaFiles(src_m6,
202                "module m6 { requires transitive m7; exports p6; }",
203                "package p6;\n"
204                + "public class C6 { p7.C7 c7; }\n");
205
206        Path src_m7 = src.resolve("m7");
207        tb.writeJavaFiles(src_m7,
208                "module m7 { requires static m8; exports p7; }",
209                "package p7;\n"
210                + "public class C7 { p8.C8 c8; }\n");
211
212        Path src_m8 = src.resolve("m8");
213        tb.writeJavaFiles(src_m8,
214                "module m8 { exports p8; }",
215                "package p8;\n"
216                        + "public class C8 { }\n");
217
218        return src;
219    }
220
221    @Test
222    public void testRequiresStatic(Path base) throws Exception {
223        Path src = base.resolve("src");
224        Path m1 = src.resolve("m1");
225        tb.writeJavaFiles(m1,
226                "module m1 { exports m1; }",
227                "package m1;" +
228                "public class Api { }\n");
229
230        Path classes = base.resolve("classes");
231        Path m1Classes = classes.resolve("m1");
232        Files.createDirectories(m1Classes);
233
234        new JavacTask(tb, Task.Mode.CMDLINE)
235                .files(findJavaFiles(m1))
236                .outdir(m1Classes)
237                .run()
238                .writeAll();
239
240        Path m3 = src.resolve("m3");
241        tb.writeJavaFiles(m3,
242                "module m3 { requires static m1; }",
243                "package m3;\n" +
244                "public class Test {\n" +
245                "    public static void main(String... args) {\n" +
246                "        try {\n" +
247                "           Class.forName(\"m1.Api\");\n" +
248                "        } catch (ClassNotFoundException e) {\n" +
249                "            System.err.println(\"ok\");\n" +
250                "        }\n" +
251                "    }\n" +
252                "}",
253                "package m3;\n" +
254                "public class ApiUse{\n" +
255                "    m1.Api api;\n" +
256                "}");
257
258        Path m3Classes = classes.resolve("m3");
259        Files.createDirectories(m3Classes);
260
261        new JavacTask(tb, Task.Mode.CMDLINE)
262                .options("--module-path", m1Classes.toString())
263                .files(findJavaFiles(m3))
264                .outdir(m3Classes)
265                .run()
266                .writeAll();
267
268        String log = new JavaTask(tb)
269                .vmOptions("--module-path", m3Classes.toString(), "--add-modules", "m3")
270                .className("m3.Test")
271                .run()
272                .writeAll()
273                .getOutput(OutputKind.STDERR);
274
275        String expected = "ok" + System.getProperty("line.separator");
276
277        if (!expected.equals(log)) {
278            throw new AssertionError("Unexpected output: " + log);
279        }
280    }
281
282    @Test
283    public void testRequiresTransitiveStatic(Path base) throws Exception {
284        Path src = base.resolve("src");
285        Path m1 = src.resolve("m1");
286        tb.writeJavaFiles(m1,
287                "module m1 { exports m1; }",
288                "package m1;" +
289                "public class Api { }\n");
290
291        Path classes = base.resolve("classes");
292        Path m1Classes = classes.resolve("m1");
293        Files.createDirectories(m1Classes);
294
295        new JavacTask(tb, Task.Mode.CMDLINE)
296                .files(findJavaFiles(m1))
297                .outdir(m1Classes)
298                .run()
299                .writeAll();
300
301        Path m2 = src.resolve("m2");
302        tb.writeJavaFiles(m2,
303                "module m2 { requires transitive static m1; }");
304
305        Path m2Classes = classes.resolve("m2");
306        Files.createDirectories(m2Classes);
307
308        new JavacTask(tb, Task.Mode.CMDLINE)
309                .options("--module-path", m1Classes.toString())
310                .files(findJavaFiles(m2))
311                .outdir(m2Classes)
312                .run()
313                .writeAll();
314
315        Path m3 = src.resolve("m3");
316        tb.writeJavaFiles(m3,
317                "module m3 { requires m2; }",
318                "package m3;\n" +
319                "public class Test {\n" +
320                "    public static void main(String... args) {\n" +
321                "        try {\n" +
322                "           Class.forName(\"m1.Api\");\n" +
323                "        } catch (ClassNotFoundException e) {\n" +
324                "            System.err.println(\"ok\");\n" +
325                "        }\n" +
326                "    }\n" +
327                "}",
328                "package m3;\n" +
329                "public class ApiUse{\n" +
330                "    m1.Api api;\n" +
331                "}");
332
333        Path m3Classes = classes.resolve("m3");
334        Files.createDirectories(m3Classes);
335
336        new JavacTask(tb, Task.Mode.CMDLINE)
337                .options("--module-path", m1Classes.toString() + File.pathSeparator + m2Classes.toString())
338                .files(findJavaFiles(m3))
339                .outdir(m3Classes)
340                .run()
341                .writeAll();
342
343        String log = new JavaTask(tb)
344                .vmOptions("--module-path", m2Classes.toString() + File.pathSeparator + m3Classes.toString(),
345                           "--add-modules", "m3")
346                .className("m3.Test")
347                .run()
348                .writeAll()
349                .getOutput(OutputKind.STDERR);
350
351        String expected = "ok" + System.getProperty("line.separator");
352
353        if (!expected.equals(log)) {
354            throw new AssertionError("Unexpected output: " + log);
355        }
356    }
357
358    @Test
359    public void testRequiresStaticTransitive(Path base) throws Exception {
360        Path src = base.resolve("src");
361        Path m1 = src.resolve("m1");
362        tb.writeJavaFiles(m1,
363                "module m1 { exports m1; }",
364                "package m1;" +
365                "public class Api { }\n");
366
367        Path classes = base.resolve("classes");
368        Path m1Classes = classes.resolve("m1");
369        Files.createDirectories(m1Classes);
370
371        new JavacTask(tb, Task.Mode.CMDLINE)
372                .files(findJavaFiles(m1))
373                .outdir(m1Classes)
374                .run()
375                .writeAll();
376
377        Path m2 = src.resolve("m2");
378        tb.writeJavaFiles(m2,
379                "module m2 { requires transitive static m1; }");
380
381        Path m2Classes = classes.resolve("m2");
382        Files.createDirectories(m2Classes);
383
384        new JavacTask(tb, Task.Mode.CMDLINE)
385                .options("--module-path", m1Classes.toString())
386                .files(findJavaFiles(m2))
387                .outdir(m2Classes)
388                .run()
389                .writeAll();
390    }
391}
392