AddReadsTest.java revision 3294:9adfb22ff08f
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 Test the -XaddReads option
27 * @library /tools/lib
28 * @modules jdk.compiler/com.sun.tools.javac.api
29 *          jdk.compiler/com.sun.tools.javac.main
30 *          jdk.jdeps/com.sun.tools.javap
31 * @build ToolBox ModuleTestBase
32 * @run main AddReadsTest
33 */
34
35import java.nio.file.Files;
36import java.nio.file.Path;
37import java.util.Set;
38
39import javax.annotation.processing.AbstractProcessor;
40import javax.annotation.processing.RoundEnvironment;
41import javax.annotation.processing.SupportedAnnotationTypes;
42import javax.lang.model.SourceVersion;
43import javax.lang.model.element.ModuleElement;
44import javax.lang.model.element.ModuleElement.RequiresDirective;
45import javax.lang.model.element.TypeElement;
46import javax.lang.model.util.ElementFilter;
47
48public class AddReadsTest extends ModuleTestBase {
49
50    public static void main(String... args) throws Exception {
51        new AddReadsTest().runTests();
52    }
53
54    @Test
55    void testAddReads(Path base) throws Exception {
56        Path src = base.resolve("src");
57        Path src_m1 = src.resolve("m1");
58        tb.writeJavaFiles(src_m1,
59                          "module m1 { exports api; }",
60                          "package api; public class Api { }");
61        Path src_m2 = src.resolve("m2");
62        tb.writeJavaFiles(src_m2,
63                          "module m2 { }",
64                          "package test; public class Test extends api.Api { }");
65        Path classes = base.resolve("classes");
66        tb.createDirectories(classes);
67
68        String log = tb.new JavacTask()
69                .options("-XDrawDiagnostics",
70                         "-modulesourcepath", src.toString())
71                .outdir(classes)
72                .files(findJavaFiles(src))
73                .run(ToolBox.Expect.FAIL)
74                .writeAll()
75                .getOutput(ToolBox.OutputKind.DIRECT);
76
77        if (!log.contains("Test.java:1:44: compiler.err.not.def.access.package.cant.access: api.Api, api"))
78            throw new Exception("expected output not found");
79
80        //test add dependencies:
81        tb.new JavacTask()
82                .options("-XaddReads:m2=m1",
83                         "-modulesourcepath", src.toString(),
84                         "-processor", VerifyRequires.class.getName())
85                .outdir(classes)
86                .files(findJavaFiles(src))
87                .run()
88                .writeAll();
89
90        String decompiled = tb.new JavapTask()
91                .options("-verbose", classes.resolve("m2").resolve("module-info.class").toString())
92                .run()
93                .getOutput(ToolBox.OutputKind.DIRECT);
94
95        if (decompiled.contains("m1")) {
96            throw new Exception("Incorrectly refers to m1 module.");
97        }
98
99        //cyclic dependencies OK when created through addReads:
100        tb.new JavacTask()
101                .options("-XaddReads:m2=m1,m1=m2",
102                         "-modulesourcepath", src.toString())
103                .outdir(classes)
104                .files(findJavaFiles(src))
105                .run()
106                .writeAll();
107
108        tb.writeJavaFiles(src_m2,
109                          "module m2 { requires m1; }");
110
111        tb.new JavacTask()
112                .options("-XaddReads:m1=m2",
113                         "-modulesourcepath", src.toString())
114                .outdir(classes)
115                .files(findJavaFiles(src))
116                .run()
117                .writeAll();
118    }
119
120    @SupportedAnnotationTypes("*")
121    public static final class VerifyRequires extends AbstractProcessor {
122
123        @Override
124        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
125            ModuleElement m2Module = processingEnv.getElementUtils().getModuleElement("m2");
126            if (m2Module == null) {
127                throw new AssertionError("Cannot find the m2 module!");
128            }
129            boolean foundM1 = false;
130            for (RequiresDirective rd : ElementFilter.requiresIn(m2Module.getDirectives())) {
131                foundM1 |= rd.getDependency().getSimpleName().contentEquals("m1");
132            }
133            if (!foundM1) {
134                throw new AssertionError("Cannot find the dependency on m1 module!");
135            }
136            return false;
137        }
138
139        @Override
140        public SourceVersion getSupportedSourceVersion() {
141            return SourceVersion.latest();
142        }
143
144    }
145
146    @Test
147    void testAddReadsUnnamedModule(Path base) throws Exception {
148        Path jar = prepareTestJar(base);
149
150        Path moduleSrc = base.resolve("module-src");
151        Path m1 = moduleSrc.resolve("m1");
152
153        Path classes = base.resolve("classes");
154
155        Files.createDirectories(classes);
156
157        tb.writeJavaFiles(m1,
158                          "module m1 { }",
159                          "package impl; public class Impl { api.Api api; }");
160
161        tb.new JavacTask()
162          .options("-classpath", jar.toString(),
163                   "-XaddReads:m1=ALL-UNNAMED",
164                   "-XDrawDiagnostics")
165          .outdir(classes)
166          .files(findJavaFiles(moduleSrc))
167          .run()
168          .writeAll();
169    }
170
171    @Test
172    void testAddReadsUnnamedModulePackageConflict(Path base) throws Exception {
173        Path jar = prepareTestJar(base);
174
175        Path moduleSrc = base.resolve("module-src");
176        Path m1 = moduleSrc.resolve("m1");
177
178        Path classes = base.resolve("classes");
179
180        Files.createDirectories(classes);
181
182        tb.writeJavaFiles(m1,
183                          "module m1 { }",
184                          "package api; public class Api { public static void test() { } }",
185                          "package impl; public class Impl { { api.Api.test(); } }");
186
187        tb.new JavacTask()
188          .options("-classpath", jar.toString(),
189                   "-modulesourcepath", moduleSrc.toString(),
190                   "-XaddReads:m1=ALL-UNNAMED",
191                   "-XDrawDiagnostics")
192          .outdir(classes)
193          .files(m1.resolve("impl").resolve("Impl.java"))
194          .run()
195          .writeAll();
196    }
197
198    @Test
199    void testAddReadsUnnamedToJavaBase(Path base) throws Exception {
200        Path jar = prepareTestJar(base);
201        Path src = base.resolve("src");
202        Path classes = base.resolve("classes");
203
204        Files.createDirectories(classes);
205
206        tb.writeJavaFiles(src,
207                          "package impl; public class Impl { api.Api a; }");
208
209        tb.new JavacTask()
210          .options("-classpath", jar.toString(),
211                   "-XaddReads:java.base=ALL-UNNAMED",
212                   "-Xmodule:java.base")
213          .outdir(classes)
214          .files(src.resolve("impl").resolve("Impl.java"))
215          .run()
216          .writeAll();
217    }
218
219    @Test
220    void testAddReadsToJavaBase(Path base) throws Exception {
221        Path src = base.resolve("src");
222        Path classes = base.resolve("classes");
223
224        Files.createDirectories(classes);
225
226        tb.writeJavaFiles(src,
227                          "package impl; public class Impl { javax.swing.JButton b; }");
228
229        tb.new JavacTask()
230          .options("-XaddReads:java.base=java.desktop",
231                   "-Xmodule:java.base")
232          .outdir(classes)
233          .files(findJavaFiles(src))
234          .run()
235          .writeAll();
236    }
237
238    private Path prepareTestJar(Path base) throws Exception {
239        Path legacySrc = base.resolve("legacy-src");
240        tb.writeJavaFiles(legacySrc,
241                          "package api; public abstract class Api {}");
242        Path legacyClasses = base.resolve("legacy-classes");
243        Files.createDirectories(legacyClasses);
244
245        String log = tb.new JavacTask()
246                .options()
247                .outdir(legacyClasses)
248                .files(findJavaFiles(legacySrc))
249                .run()
250                .writeAll()
251                .getOutput(ToolBox.OutputKind.DIRECT);
252
253        if (!log.isEmpty()) {
254            throw new Exception("unexpected output: " + log);
255        }
256
257        Path lib = base.resolve("lib");
258
259        Files.createDirectories(lib);
260
261        Path jar = lib.resolve("test-api-1.0.jar");
262
263        tb.new JarTask(jar)
264          .baseDir(legacyClasses)
265          .files("api/Api.class")
266          .run();
267
268        return jar;
269    }
270
271    @Test
272    void testX(Path base) throws Exception {
273        Path src = base.resolve("src");
274        Path src_m1 = src.resolve("m1");
275        tb.writeJavaFiles(src_m1,
276                          "module m1 { provides java.lang.Runnable with impl.Impl; }",
277                          "package impl; public class Impl implements Runnable { public void run() { } }");
278        Path classes = base.resolve("classes");
279        tb.createDirectories(classes);
280
281        tb.new JavacTask()
282                .options("-modulesourcepath", src.toString())
283                .outdir(classes)
284                .files(findJavaFiles(src))
285                .run()
286                .writeAll();
287
288        Path unnamedSrc = base.resolve("unnamed-src");
289        Path unnamedClasses = base.resolve("unnamed-classes");
290
291        Files.createDirectories(unnamedClasses);
292
293        tb.writeJavaFiles(unnamedSrc,
294                          "package impl; public class Impl { }");
295
296        tb.new JavacTask()
297          .options("-XaddReads:m1=ALL-UNNAMED",
298                   "-Xmodule:m1",
299                   "-modulepath", classes.toString())
300          .outdir(unnamedClasses)
301          .files(findJavaFiles(unnamedSrc))
302          .run()
303          .writeAll();
304    }
305}
306