EdgeCases.java revision 3294:9adfb22ff08f
1/*
2 * Copyright (c) 2015, 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 multi-module mode compilation
27 * @library /tools/lib
28 * @modules
29 *      jdk.compiler/com.sun.tools.javac.api
30 *      jdk.compiler/com.sun.tools.javac.code
31 *      jdk.compiler/com.sun.tools.javac.main
32 *      jdk.jdeps/com.sun.tools.javap
33 * @build ToolBox ModuleTestBase
34 * @run main EdgeCases
35 */
36
37import java.io.Writer;
38import java.nio.file.Files;
39import java.nio.file.Path;
40import java.nio.file.Paths;
41import java.util.Arrays;
42import java.util.HashSet;
43import java.util.List;
44import java.util.Objects;
45import java.util.Set;
46
47import javax.lang.model.element.Element;
48import javax.tools.JavaCompiler;
49import javax.tools.JavaFileObject;
50import javax.tools.StandardJavaFileManager;
51import javax.tools.ToolProvider;
52
53import com.sun.source.tree.CompilationUnitTree;
54import com.sun.source.util.JavacTask;
55import com.sun.tools.javac.api.JavacTaskImpl;
56import com.sun.tools.javac.code.Symbol.ModuleSymbol;
57
58public class EdgeCases extends ModuleTestBase {
59
60    public static void main(String... args) throws Exception {
61        new EdgeCases().runTests();
62    }
63
64    @Test
65    void testAddExportUndefinedModule(Path base) throws Exception {
66        Path src = base.resolve("src");
67        tb.writeJavaFiles(src, "package test; import undef.Any; public class Test {}");
68        Path classes = base.resolve("classes");
69        tb.createDirectories(classes);
70
71        List<String> log = tb.new JavacTask()
72                .options("-XaddExports:undef/undef=ALL-UNNAMED", "-XDrawDiagnostics")
73                .outdir(classes)
74                .files(findJavaFiles(src))
75                .run(ToolBox.Expect.FAIL)
76                .writeAll()
77                .getOutputLines(ToolBox.OutputKind.DIRECT);
78
79        List<String> expected = Arrays.asList("- compiler.err.cant.find.module: undef",
80                                              "Test.java:1:27: compiler.err.doesnt.exist: undef",
81                                              "2 errors");
82
83        if (!expected.equals(log))
84            throw new Exception("expected output not found: " + log);
85    }
86
87    @Test
88    void testModuleSymbolOutterMostClass(Path base) throws Exception {
89        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
90        try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
91            Path moduleSrc = base.resolve("module-src");
92            Path m1 = moduleSrc.resolve("m1");
93
94            tb.writeJavaFiles(m1, "module m1 { }");
95
96            Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(moduleSrc));
97            JavacTask task = (JavacTask) compiler.getTask(null, fm, null, null, null, files);
98
99            task.analyze();
100
101            ModuleSymbol msym = (ModuleSymbol) task.getElements().getModuleElement("m1");
102
103            msym.outermostClass();
104        }
105    }
106
107    @Test
108    void testParseEnterAnalyze(Path base) throws Exception {
109        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
110        try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
111            Path moduleSrc = base.resolve("module-src");
112            Path m1 = moduleSrc.resolve("m1");
113
114            tb.writeJavaFiles(m1, "module m1 { }",
115                                  "package p;",
116                                  "package p; class T { }");
117
118            Path classes = base.resolve("classes");
119            Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(moduleSrc));
120            List<String> options = Arrays.asList("-d", classes.toString(), "-Xpkginfo:always");
121            JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, fm, null, options, null, files);
122
123            Iterable<? extends CompilationUnitTree> parsed = task.parse();
124            Iterable<? extends Element> entered = task.enter(parsed);
125            Iterable<? extends Element> analyzed = task.analyze(entered);
126            Iterable<? extends JavaFileObject> generatedFiles = task.generate(analyzed);
127
128            Set<String> generated = new HashSet<>();
129
130            for (JavaFileObject jfo : generatedFiles) {
131                generated.add(jfo.getName());
132            }
133
134            Set<String> expected = new HashSet<>(
135                    Arrays.asList(Paths.get("testParseEnterAnalyze", "classes", "p", "package-info.class").toString(),
136                                  Paths.get("testParseEnterAnalyze", "classes", "module-info.class").toString(),
137                                  Paths.get("testParseEnterAnalyze", "classes", "p", "T.class").toString())
138            );
139
140            if (!Objects.equals(expected, generated))
141                throw new AssertionError("Incorrect generated files: " + generated);
142        }
143    }
144
145    @Test
146    void testModuleImplicitModuleBoundaries(Path base) throws Exception {
147        Path src = base.resolve("src");
148        Path src_m1 = src.resolve("m1");
149        tb.writeJavaFiles(src_m1,
150                          "module m1 { exports api1; }",
151                          "package api1; public class Api1 { public void call() { } }");
152        Path src_m2 = src.resolve("m2");
153        tb.writeJavaFiles(src_m2,
154                          "module m2 { requires m1; exports api2; }",
155                          "package api2; public class Api2 { public static api1.Api1 get() { return null; } }");
156        Path src_m3 = src.resolve("m3");
157        tb.writeJavaFiles(src_m3,
158                          "module m3 { requires m2; }",
159                          "package test; public class Test { { api2.Api2.get().call(); api2.Api2.get().toString(); } }");
160        Path classes = base.resolve("classes");
161        tb.createDirectories(classes);
162
163        String log = tb.new JavacTask()
164                .options("-XDrawDiagnostics",
165                         "-modulesourcepath", src.toString())
166                .outdir(classes)
167                .files(findJavaFiles(src))
168                .run(ToolBox.Expect.FAIL)
169                .writeAll()
170                .getOutput(ToolBox.OutputKind.DIRECT);
171
172        if (!log.contains("Test.java:1:52: compiler.err.not.def.access.class.intf.cant.access: call(), api1.Api1") ||
173            !log.contains("Test.java:1:76: compiler.err.not.def.access.class.intf.cant.access: toString(), java.lang.Object"))
174            throw new Exception("expected output not found");
175    }
176
177    @Test
178    void testAssignClassToAutomaticModule(Path base) throws Exception {
179        //check that if a ClassSymbol belongs to an automatic module, it is properly assigned and not
180        //duplicated when being accessed through a classfile.
181        Path automaticSrc = base.resolve("automaticSrc");
182        tb.writeJavaFiles(automaticSrc, "package api1; public class Api1 {}");
183        Path automaticClasses = base.resolve("automaticClasses");
184        tb.createDirectories(automaticClasses);
185
186        String automaticLog = tb.new JavacTask()
187                                .outdir(automaticClasses)
188                                .files(findJavaFiles(automaticSrc))
189                                .run()
190                                .writeAll()
191                                .getOutput(ToolBox.OutputKind.DIRECT);
192
193        if (!automaticLog.isEmpty())
194            throw new Exception("expected output not found: " + automaticLog);
195
196        Path modulePath = base.resolve("module-path");
197
198        Files.createDirectories(modulePath);
199
200        Path automaticJar = modulePath.resolve("m1-1.0.jar");
201
202        tb.new JarTask(automaticJar)
203          .baseDir(automaticClasses)
204          .files("api1/Api1.class")
205          .run();
206
207        Path src = base.resolve("src");
208        Path src_m2 = src.resolve("m2");
209        tb.writeJavaFiles(src_m2,
210                          "module m2 { requires m1; exports api2; }",
211                          "package api2; public class Api2 { public static api1.Api1 get() { return null; } }");
212        Path src_m3 = src.resolve("m3");
213        tb.writeJavaFiles(src_m3,
214                          "module m3 { requires m1; requires m2; }",
215                          "package test; public class Test { { api2.Api2.get(); api1.Api1 a1; } }");
216        Path classes = base.resolve("classes");
217        tb.createDirectories(classes);
218
219        tb.new JavacTask()
220                .options("-modulepath", modulePath.toString(),
221                         "-modulesourcepath", src.toString())
222                .outdir(classes)
223                .files(findJavaFiles(src_m2))
224                .run()
225                .writeAll();
226
227        tb.new JavacTask()
228                .options("-modulepath", modulePath.toString(),
229                         "-modulesourcepath", src.toString())
230                .outdir(classes)
231                .files(findJavaFiles(src_m3))
232                .run()
233                .writeAll();
234    }
235
236    @Test
237    void testEmptyImplicitModuleInfo(Path base) throws Exception {
238        Path src = base.resolve("src");
239        Path src_m1 = src.resolve("m1");
240        Files.createDirectories(src_m1);
241        try (Writer w = Files.newBufferedWriter(src_m1.resolve("module-info.java"))) {}
242        tb.writeJavaFiles(src_m1,
243                          "package test; public class Test {}");
244        Path classes = base.resolve("classes");
245        tb.createDirectories(classes);
246
247        tb.new JavacTask()
248                .options("-sourcepath", src_m1.toString(),
249                         "-XDrawDiagnostics")
250                .outdir(classes)
251                .files(findJavaFiles(src_m1.resolve("test")))
252                .run(ToolBox.Expect.FAIL)
253                .writeAll();
254
255        tb.writeJavaFiles(src_m1,
256                          "module m1 {}");
257
258        tb.new JavacTask()
259                .options("-sourcepath", src_m1.toString())
260                .outdir(classes)
261                .files(findJavaFiles(src_m1.resolve("test")))
262                .run()
263                .writeAll();
264
265    }
266
267}
268