QueryBeforeEnter.java revision 3294:9adfb22ff08f
1/*
2 * Copyright (c) 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 module resolution
27 * @library /tools/lib
28 * @modules
29 *      jdk.compiler/com.sun.tools.javac.api
30 *      jdk.compiler/com.sun.tools.javac.main
31 *      jdk.jdeps/com.sun.tools.javap
32 * @build ToolBox ModuleTestBase
33 * @run main QueryBeforeEnter
34 */
35
36import java.io.File;
37import java.io.OutputStream;
38import java.nio.file.*;
39import java.util.Arrays;
40import java.util.Set;
41
42import javax.annotation.processing.AbstractProcessor;
43import javax.annotation.processing.RoundEnvironment;
44import javax.annotation.processing.SupportedAnnotationTypes;
45import javax.annotation.processing.SupportedSourceVersion;
46import javax.lang.model.SourceVersion;
47import javax.lang.model.element.TypeElement;
48import javax.tools.JavaCompiler;
49import javax.tools.StandardJavaFileManager;
50import javax.tools.ToolProvider;
51
52import com.sun.source.util.JavacTask;
53import com.sun.source.util.Plugin;
54import com.sun.source.util.TaskEvent;
55import com.sun.source.util.TaskListener;
56import com.sun.tools.javac.Main;
57
58public class QueryBeforeEnter extends ModuleTestBase {
59    public static void main(String... args) throws Exception {
60        QueryBeforeEnter t = new QueryBeforeEnter();
61        t.runTests();
62    }
63
64    @Test
65    void testEmpty(Path base) throws Exception {
66        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
67        JavacTask task = (JavacTask) javaCompiler.getTask(null, null, null, null, null, null);
68        TypeElement jlString = task.getElements().getTypeElement("java.lang.String");
69
70        assertNotNull(jlString);
71    }
72
73    @Test
74    void testUnnamed(Path base) throws Exception {
75        Path moduleSrc = base.resolve("module-src");
76        Path m1 = moduleSrc.resolve("m1");
77
78        tb.writeJavaFiles(m1,
79                          "module m1 { exports m1; }",
80                          "package m1; public class M1 {}");
81
82        Path m2 = moduleSrc.resolve("m2");
83
84        tb.writeJavaFiles(m2,
85                          "module m2 { exports m2; }",
86                          "package m2; public class M2 {}");
87
88        Path modulePath = base.resolve("module-path");
89
90        Files.createDirectories(modulePath);
91
92        tb.new JavacTask()
93                .options("-modulesourcepath", moduleSrc.toString())
94                .outdir(modulePath)
95                .files(findJavaFiles(moduleSrc))
96                .run()
97                .writeAll();
98
99        Path cpSrc = base.resolve("cp-src");
100
101        tb.writeJavaFiles(cpSrc,
102                          "package cp; public class CP {}");
103
104        Path cp = base.resolve("cp");
105
106        Files.createDirectories(cp);
107
108        tb.new JavacTask()
109                .outdir(cp)
110                .files(findJavaFiles(cpSrc))
111                .run()
112                .writeAll();
113
114        Path src = base.resolve("src");
115
116        tb.writeJavaFiles(src,
117                          "package test; public class Test1 {}",
118                          "package test; public class Test2 {}");
119
120        Path out = base.resolve("out");
121
122        Files.createDirectories(out);
123
124        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
125        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
126            JavacTask task = (JavacTask) javaCompiler.getTask(null,
127                                                              null,
128                                                              d -> { throw new IllegalStateException(d.toString()); },
129                                                              Arrays.asList("-modulepath", modulePath.toString(),
130                                                                            "-classpath", cp.toString(),
131                                                                            "-sourcepath", src.toString()),
132                                                              null,
133                                                              fm.getJavaFileObjects(src.resolve("test").resolve("Test2.java")));
134            assertNotNull(task.getElements().getTypeElement("java.lang.String"));
135            assertNotNull(task.getElements().getTypeElement("javax.tools.ToolProvider"));
136            assertNull(task.getElements().getTypeElement("m1.M1"));
137            assertNull(task.getElements().getTypeElement("m2.M2"));
138            assertNotNull(task.getElements().getTypeElement("cp.CP"));
139            assertNotNull(task.getElements().getTypeElement("test.Test1"));
140            assertNotNull(task.getElements().getTypeElement("test.Test2"));
141            assertNotNull(task.getElements().getModuleElement("java.base"));
142            assertNotNull(task.getElements().getModuleElement("java.compiler"));
143            assertNull(task.getElements().getModuleElement("m1"));
144            assertNull(task.getElements().getModuleElement("m2"));
145        }
146    }
147
148    @Test
149    void testSingleNamed(Path base) throws Exception {
150        Path moduleSrc = base.resolve("module-src");
151        Path m1 = moduleSrc.resolve("m1");
152
153        tb.writeJavaFiles(m1,
154                          "module m1 { exports m1; }",
155                          "package m1; public class M1 {}");
156
157        Path m2 = moduleSrc.resolve("m2");
158
159        tb.writeJavaFiles(m2,
160                          "module m2 { exports m2; }",
161                          "package m2; public class M2 {}");
162
163        Path modulePath = base.resolve("module-path");
164
165        Files.createDirectories(modulePath);
166
167        tb.new JavacTask()
168                .options("-modulesourcepath", moduleSrc.toString())
169                .outdir(modulePath)
170                .files(findJavaFiles(moduleSrc))
171                .run()
172                .writeAll();
173
174        Path cpSrc = base.resolve("cp-src");
175
176        tb.writeJavaFiles(cpSrc,
177                          "package cp; public class CP {}");
178
179        Path cp = base.resolve("cp");
180
181        Files.createDirectories(cp);
182
183        tb.new JavacTask()
184                .outdir(cp)
185                .files(findJavaFiles(cpSrc))
186                .run()
187                .writeAll();
188
189        Path src = base.resolve("src");
190
191        tb.writeJavaFiles(src,
192                          "module test { requires java.base; requires m1; } ",
193                          "package test; public class Test {}");
194
195        Path out = base.resolve("out");
196
197        Files.createDirectories(out);
198
199        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
200        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
201            JavacTask task = (JavacTask) javaCompiler.getTask(null,
202                                                              null,
203                                                              d -> { throw new IllegalStateException(d.toString()); },
204                                                              Arrays.asList("-modulepath", modulePath.toString(),
205                                                                            "-classpath", cp.toString(),
206                                                                            "-sourcepath", src.toString()),
207                                                              null,
208                                                              fm.getJavaFileObjects(findJavaFiles(src)));
209            assertNotNull(task.getElements().getTypeElement("java.lang.String"));
210            assertNull(task.getElements().getTypeElement("javax.tools.ToolProvider"));
211            assertNotNull(task.getElements().getTypeElement("m1.M1"));
212            assertNull(task.getElements().getTypeElement("m2.M2"));
213            assertNotNull(task.getElements().getTypeElement("test.Test"));
214            assertNotNull(task.getElements().getModuleElement("java.base"));
215            assertNull(task.getElements().getModuleElement("java.compiler"));
216            assertNotNull(task.getElements().getModuleElement("m1"));
217            assertNull(task.getElements().getModuleElement("m2"));
218            assertNotNull(task.getElements().getModuleElement("test"));
219        }
220    }
221
222    @Test
223    void testMultiModule(Path base) throws Exception {
224        Path modulePathSrc = base.resolve("module-path-src");
225        Path m1 = modulePathSrc.resolve("m1");
226
227        tb.writeJavaFiles(m1,
228                          "module m1 { exports m1; }",
229                          "package m1; public class M1 {}");
230
231        Path m2 = modulePathSrc.resolve("m2");
232
233        tb.writeJavaFiles(m2,
234                          "module m2 { exports m2; }",
235                          "package m2; public class M2 {}");
236
237        Path modulePath = base.resolve("module-path");
238
239        Files.createDirectories(modulePath);
240
241        tb.new JavacTask()
242                .options("-modulesourcepath", modulePathSrc.toString())
243                .outdir(modulePath)
244                .files(findJavaFiles(modulePathSrc))
245                .run()
246                .writeAll();
247
248        Path cpSrc = base.resolve("cp-src");
249
250        tb.writeJavaFiles(cpSrc,
251                          "package cp; public class CP {}");
252
253        Path cp = base.resolve("cp");
254
255        Files.createDirectories(cp);
256
257        tb.new JavacTask()
258                .outdir(cp)
259                .files(findJavaFiles(cpSrc))
260                .run()
261                .writeAll();
262
263        Path moduleSrc = base.resolve("module-src");
264        Path m3 = moduleSrc.resolve("m3");
265
266        tb.writeJavaFiles(m3,
267                          "module m3 { requires m1; exports m3; }",
268                          "package m3; public class M3 {  }");
269
270        Path m4 = moduleSrc.resolve("m4");
271
272        tb.writeJavaFiles(m4,
273                          "module m4 { exports m4; }",
274                          "package m4; public class M4 {}");
275
276        Path out = base.resolve("out");
277
278        Files.createDirectories(out);
279
280        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
281        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
282            JavacTask task = (JavacTask) javaCompiler.getTask(null,
283                                                              null,
284                                                              d -> { throw new IllegalStateException(d.toString()); },
285                                                              Arrays.asList("-modulepath", modulePath.toString(),
286                                                                            "-classpath", cp.toString(),
287                                                                            "-modulesourcepath", moduleSrc.toString(),
288                                                                            "-d", out.toString()),
289                                                              null,
290                                                              fm.getJavaFileObjects(findJavaFiles(moduleSrc)));
291            assertNotNull(task.getElements().getTypeElement("java.lang.String"));
292            assertNull(task.getElements().getTypeElement("javax.tools.ToolProvider"));
293            assertNotNull(task.getElements().getTypeElement("m1.M1"));
294            assertNull(task.getElements().getTypeElement("m2.M2"));
295            assertNotNull(task.getElements().getTypeElement("m3.M3"));
296            assertNotNull(task.getElements().getTypeElement("m4.M4"));
297            assertNotNull(task.getElements().getModuleElement("java.base"));
298            assertNull(task.getElements().getModuleElement("java.compiler"));
299            assertNotNull(task.getElements().getModuleElement("m1"));
300            assertNull(task.getElements().getModuleElement("m2"));
301            assertNotNull(task.getElements().getModuleElement("m3"));
302            assertNotNull(task.getElements().getModuleElement("m4"));
303        }
304    }
305
306    @Test
307    void testTooSoon(Path base) throws Exception {
308        Path src = base.resolve("src");
309
310        tb.writeJavaFiles(src,
311                          "package test; public class Test {}");
312
313        Path out = base.resolve("out");
314
315        Files.createDirectories(out);
316
317        Path reg = base.resolve("reg");
318        Path regFile = reg.resolve("META-INF").resolve("services").resolve(Plugin.class.getName());
319
320        Files.createDirectories(regFile.getParent());
321
322        try (OutputStream regOut = Files.newOutputStream(regFile)) {
323            regOut.write(PluginImpl.class.getName().getBytes());
324        }
325
326        String processorPath = System.getProperty("test.class.path") + File.pathSeparator + reg.toString();
327
328        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
329        Path testSource = src.resolve("test").resolve("Test.java");
330        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
331            JavacTask task = (JavacTask) javaCompiler.getTask(null,
332                                                              null,
333                                                              d -> { throw new IllegalStateException(d.toString()); },
334                                                              Arrays.asList("-processorpath", processorPath,
335                                                                            "-processor", AP.class.getName(),
336                                                                            "-Xplugin:test"),
337                                                              null,
338                                                              fm.getJavaFileObjects(testSource));
339            task.call();
340        }
341
342        Main.compile(new String[] {"-processorpath", processorPath,
343                                   "-Xplugin:test",
344                                   testSource.toString()});
345    }
346
347    public static class PluginImpl implements Plugin {
348
349        @Override
350        public String getName() {
351            return "test";
352        }
353
354        @Override
355        public void init(JavacTask task, String... args) {
356            task.addTaskListener(new TaskListener() {
357                boolean wasEntered;
358                @Override
359                public void started(TaskEvent e) {
360                    switch (e.getKind()) {
361                        case COMPILATION: case PARSE:
362                            shouldFail(e.getKind());
363                            break;
364                        case ANNOTATION_PROCESSING: case ENTER:
365                            if (wasEntered) {
366                                shouldPass(e.getKind());
367                            } else {
368                                shouldFail(e.getKind());
369                            }
370                            break;
371                        default:
372                            shouldPass(e.getKind());
373                            break;
374                    }
375                }
376                @Override
377                public void finished(TaskEvent e) {
378                    switch (e.getKind()) {
379                        case PARSE:
380                            shouldFail(e.getKind());
381                            break;
382                        case ENTER:
383                            wasEntered = true;
384                            //fall-through:
385                        default:
386                            shouldPass(e.getKind());
387                            break;
388                    }
389                }
390                private void shouldFail(TaskEvent.Kind kind) {
391                    try {
392                        task.getElements().getTypeElement("java.lang.String");
393                        throw new AssertionError("Expected exception not observed; kind=" + kind.name());
394                    } catch (IllegalStateException ex) {
395                        //correct
396                    }
397                }
398                private void shouldPass(TaskEvent.Kind kind) {
399                    assertNotNull(task.getElements().getTypeElement("java.lang.String"));
400                }
401            });
402
403        }
404
405    }
406
407    @SupportedAnnotationTypes("*")
408    public static final class AP extends AbstractProcessor {
409
410        @Override
411        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
412            return false;
413        }
414
415        @Override
416        public SourceVersion getSupportedSourceVersion() {
417            return SourceVersion.latest();
418        }
419
420    }
421
422    private static void assertNotNull(Object actual) {
423        if (actual == null) {
424            throw new AssertionError("unexpected null!");
425        }
426    }
427
428    private static void assertNull(Object actual) {
429        if (actual != null) {
430            throw new AssertionError("unexpected non null!");
431        }
432    }
433
434}
435