IncubatingTest.java revision 4104:4012b3f11f0d
1/*
2 * Copyright (c) 2015, 2017, 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 8171177
27 * @summary Verify that ModuleResolution attribute flags are honored.
28 * @library /tools/lib
29 * @modules jdk.compiler/com.sun.tools.javac.api
30 *          jdk.compiler/com.sun.tools.javac.main
31 *          jdk.jdeps/com.sun.tools.classfile
32 *          jdk.jdeps/com.sun.tools.javap
33 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavapTask ModuleTestBase
34 * @run main IncubatingTest
35 */
36
37import java.io.IOException;
38import java.io.OutputStream;
39import java.net.URI;
40import java.nio.file.FileSystem;
41import java.nio.file.FileSystems;
42import java.nio.file.Files;
43import java.nio.file.Path;
44import java.util.ArrayList;
45import java.util.Arrays;
46import java.util.HashMap;
47import java.util.List;
48import java.util.Map;
49
50import com.sun.tools.classfile.Attribute;
51import com.sun.tools.classfile.Attributes;
52import com.sun.tools.classfile.ClassFile;
53import com.sun.tools.classfile.ClassWriter;
54import com.sun.tools.classfile.ConstantPool;
55import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
56import com.sun.tools.classfile.ConstantPool.CPInfo;
57import com.sun.tools.classfile.ModuleResolution_attribute;
58import toolbox.JavacTask;
59import toolbox.Task;
60import toolbox.Task.Expect;
61
62public class IncubatingTest extends ModuleTestBase {
63
64    public static void main(String... args) throws Exception {
65        new IncubatingTest().runTests();
66    }
67
68    @Test
69    public void testDoNotResolve(Path base) throws Exception {
70        Path src = base.resolve("src");
71        tb.writeJavaFiles(src,
72                          "module jdk.i { exports api; }",
73                          "package api; public class Api { }");
74        Path classes = base.resolve("classes");
75        Files.deleteIfExists(classes);
76        Path iClasses = classes.resolve("jdk.i");
77        tb.createDirectories(iClasses);
78
79        new JavacTask(tb)
80                .outdir(iClasses)
81                .files(findJavaFiles(src))
82                .run()
83                .writeAll();
84
85        copyJavaBase(classes);
86
87        Path jdkIModuleInfo = iClasses.resolve("module-info.class");
88        addModuleResolutionAttribute(jdkIModuleInfo, ModuleResolution_attribute.DO_NOT_RESOLVE_BY_DEFAULT);
89
90        Path testSrc = base.resolve("test-src");
91        tb.writeJavaFiles(testSrc,
92                          "class T { api.Api api; }");
93        Path testClasses = base.resolve("test-classes");
94        tb.createDirectories(testClasses);
95
96        List<String> log;
97        List<String> expected;
98
99        log = new JavacTask(tb)
100                .options("--system", "none",
101                         "--upgrade-module-path", classes.toString(),
102                         "-XDrawDiagnostics")
103                .outdir(testClasses)
104                .files(findJavaFiles(testSrc))
105                .run(Expect.FAIL)
106                .writeAll()
107                .getOutputLines(Task.OutputKind.DIRECT);
108
109        expected = Arrays.asList(
110                "T.java:1:11: compiler.err.package.not.visible: api, (compiler.misc.not.def.access.does.not.read.from.unnamed: api, jdk.i)",
111                "1 error"
112        );
113
114        if (!expected.equals(log)) {
115            throw new AssertionError("Unexpected output: " + log);
116        }
117
118        log = new JavacTask(tb)
119                .options("--system", "none",
120                         "--upgrade-module-path", classes.toString(),
121                         "--add-modules", "ALL-SYSTEM",
122                         "-XDrawDiagnostics")
123                .outdir(testClasses)
124                .files(findJavaFiles(testSrc))
125                .run(Expect.SUCCESS)
126                .writeAll()
127                .getOutputLines(Task.OutputKind.DIRECT);
128
129        expected = Arrays.asList("");
130
131        if (!expected.equals(log)) {
132            throw new AssertionError("Unexpected output: " + log);
133        }
134
135        new JavacTask(tb)
136                .options("--system", "none",
137                         "--upgrade-module-path", classes.toString(),
138                         "--add-modules", "jdk.i")
139                .outdir(testClasses)
140                .files(findJavaFiles(testSrc))
141                .run()
142                .writeAll();
143
144        Path testModuleSrc = base.resolve("test-module-src");
145        tb.writeJavaFiles(testModuleSrc,
146                          "module test { requires jdk.i; }", //explicit requires of an incubating module
147                          "class T { api.Api api; }");
148        Path testModuleClasses = base.resolve("test-module-classes");
149        tb.createDirectories(testModuleClasses);
150
151        new JavacTask(tb)
152                .options("--system", "none",
153                         "--upgrade-module-path", classes.toString())
154                .outdir(testModuleClasses)
155                .files(findJavaFiles(testModuleSrc))
156                .run()
157                .writeAll();
158    }
159
160    @Test
161    public void testIncubating(Path base) throws Exception {
162        Path src = base.resolve("src");
163        tb.writeJavaFiles(src,
164                          "module jdk.i { exports api; }",
165                          "package api; public class Api { }");
166        Path classes = base.resolve("classes");
167        Files.deleteIfExists(classes);
168        Path iClasses = classes.resolve("jdk.i");
169        tb.createDirectories(iClasses);
170
171        new JavacTask(tb)
172                .outdir(iClasses)
173                .files(findJavaFiles(src))
174                .run()
175                .writeAll();
176
177        Path jdkIModuleInfo = iClasses.resolve("module-info.class");
178        addModuleResolutionAttribute(jdkIModuleInfo, ModuleResolution_attribute.WARN_INCUBATING);
179
180        Path testSrc = base.resolve("test-src");
181        tb.writeJavaFiles(testSrc,
182                          "class T { api.Api api; }");
183        Path testClasses = base.resolve("test-classes");
184        tb.createDirectories(testClasses);
185
186        List<String> log;
187        List<String> expected;
188
189        log = new JavacTask(tb)
190                .options("--module-path", classes.toString(),
191                         "--add-modules", "jdk.i",
192                         "-XDrawDiagnostics",
193                         "-Werror")
194                .outdir(testClasses)
195                .files(findJavaFiles(testSrc))
196                .run(Expect.FAIL)
197                .writeAll()
198                .getOutputLines(Task.OutputKind.DIRECT);
199
200        expected = Arrays.asList(
201                "- compiler.warn.incubating.modules: jdk.i",
202                "- compiler.err.warnings.and.werror",
203                "1 error",
204                "1 warning"
205        );
206
207        if (!expected.equals(log)) {
208            throw new AssertionError("Unexpected output: " + log);
209        }
210
211        Path testModuleSrc = base.resolve("test-module-src");
212        tb.writeJavaFiles(testModuleSrc,
213                          "module test { requires jdk.i; }", //explicit requires of an incubating module
214                          "class T { api.Api api; }");
215        Path testModuleClasses = base.resolve("test-module-classes");
216        tb.createDirectories(testModuleClasses);
217
218        log = new JavacTask(tb)
219                .options("--module-path", classes.toString(),
220                         "-XDrawDiagnostics",
221                         "-Werror")
222                .outdir(testModuleClasses)
223                .files(findJavaFiles(testModuleSrc))
224                .run(Expect.FAIL)
225                .writeAll()
226                .getOutputLines(Task.OutputKind.DIRECT);
227
228        expected = Arrays.asList(
229                "- compiler.warn.incubating.modules: jdk.i",
230                "- compiler.err.warnings.and.werror",
231                "1 error",
232                "1 warning"
233        );
234
235        if (!expected.equals(log)) {
236            throw new AssertionError("Unexpected output: " + log);
237        }
238    }
239
240    private void copyJavaBase(Path targetDir) throws IOException {
241        FileSystem jrt = FileSystems.getFileSystem(URI.create("jrt:/"));
242        Path javaBase = jrt.getPath("modules", "java.base");
243
244        if (!Files.exists(javaBase)) {
245            throw new AssertionError("No java.base?");
246        }
247
248        Path javaBaseClasses = targetDir.resolve("java.base");
249
250        for (Path clazz : tb.findFiles("class", javaBase)) {
251            Path target = javaBaseClasses.resolve(javaBase.relativize(clazz).toString());
252            Files.createDirectories(target.getParent());
253            Files.copy(clazz, target);
254        }
255    }
256
257    private void addModuleResolutionAttribute(Path classfile, int resolution_flags) throws Exception {
258        ClassFile cf = ClassFile.read(classfile);
259        Attributes attrs = cf.attributes;
260        List<CPInfo> cpData = new ArrayList<>();
261        cpData.add(null);
262        for (CPInfo info : cf.constant_pool.entries()) {
263            cpData.add(info);
264            if (info.size() == 2)
265                cpData.add(null);
266        }
267        cpData.add(new CONSTANT_Utf8_info(Attribute.ModuleResolution));
268        ConstantPool newCP = new ConstantPool(cpData.toArray(new CPInfo[0]));
269        ModuleResolution_attribute res = new ModuleResolution_attribute(newCP, resolution_flags);
270        Map<String, Attribute> newAttributeMap = new HashMap<>(attrs.map);
271        newAttributeMap.put(Attribute.ModuleResolution, res);
272        Attributes newAttrs = new Attributes(newAttributeMap);
273        ClassFile newCF = new ClassFile(cf.magic,
274                                        cf.minor_version,
275                                        cf.major_version,
276                                        newCP,
277                                        cf.access_flags,
278                                        cf.this_class,
279                                        cf.super_class,
280                                        cf.interfaces,
281                                        cf.fields,
282                                        cf.methods,
283                                        newAttrs);
284        try (OutputStream out = Files.newOutputStream(classfile)) {
285            new ClassWriter().write(newCF, out);
286        }
287    }
288}
289