AddReadsTest.java revision 3747:80b576bd3631
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 --add-reads 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 *          java.desktop
32 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavapTask ModuleTestBase
33 * @run main AddReadsTest
34 */
35
36import java.nio.file.Files;
37import java.nio.file.Path;
38import java.util.Set;
39
40import javax.annotation.processing.AbstractProcessor;
41import javax.annotation.processing.RoundEnvironment;
42import javax.annotation.processing.SupportedAnnotationTypes;
43import javax.lang.model.SourceVersion;
44import javax.lang.model.element.ModuleElement;
45import javax.lang.model.element.ModuleElement.RequiresDirective;
46import javax.lang.model.element.TypeElement;
47import javax.lang.model.util.ElementFilter;
48
49import toolbox.JarTask;
50import toolbox.JavacTask;
51import toolbox.JavapTask;
52import toolbox.Task;
53
54public class AddReadsTest extends ModuleTestBase {
55
56    public static void main(String... args) throws Exception {
57        new AddReadsTest().runTests();
58    }
59
60    @Test
61    public void testAddReads(Path base) throws Exception {
62        Path src = base.resolve("src");
63        Path src_m1 = src.resolve("m1");
64        tb.writeJavaFiles(src_m1,
65                          "module m1 { exports api; }",
66                          "package api; public class Api { }");
67        Path src_m2 = src.resolve("m2");
68        tb.writeJavaFiles(src_m2,
69                          "module m2 { }",
70                          "package test; public class Test extends api.Api { }");
71        Path classes = base.resolve("classes");
72        tb.createDirectories(classes);
73
74        String log = new JavacTask(tb)
75                .options("-XDrawDiagnostics",
76                         "--module-source-path", src.toString())
77                .outdir(classes)
78                .files(findJavaFiles(src))
79                .run(Task.Expect.FAIL)
80                .writeAll()
81                .getOutput(Task.OutputKind.DIRECT);
82
83        checkOutputContains(log,
84            "Test.java:1:44: compiler.err.not.def.access.package.cant.access: api.Api, api");
85
86        //test add dependencies:
87        new JavacTask(tb)
88                .options("--add-reads", "m2=m1",
89                         "--module-source-path", src.toString(),
90                         "-processor", VerifyRequires.class.getName())
91                .outdir(classes)
92                .files(findJavaFiles(src))
93                .run()
94                .writeAll();
95
96        String decompiled = new JavapTask(tb)
97                .options("-verbose", classes.resolve("m2").resolve("module-info.class").toString())
98                .run()
99                .getOutput(Task.OutputKind.DIRECT);
100
101        if (decompiled.contains("m1")) {
102            throw new Exception("Incorrectly refers to m1 module.");
103        }
104
105        //cyclic dependencies OK when created through addReads:
106        new JavacTask(tb)
107                .options("--add-reads", "m2=m1",
108                         "--add-reads", "m1=m2",
109                         "--module-source-path", src.toString())
110                .outdir(classes)
111                .files(findJavaFiles(src))
112                .run()
113                .writeAll();
114
115        tb.writeJavaFiles(src_m2,
116                          "module m2 { requires m1; }");
117
118        new JavacTask(tb)
119                .options("--add-reads", "m1=m2",
120                         "--module-source-path", src.toString())
121                .outdir(classes)
122                .files(findJavaFiles(src))
123                .run()
124                .writeAll();
125    }
126
127    @SupportedAnnotationTypes("*")
128    public static final class VerifyRequires extends AbstractProcessor {
129
130        @Override
131        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
132            ModuleElement m2Module = processingEnv.getElementUtils().getModuleElement("m2");
133            if (m2Module == null) {
134                throw new AssertionError("Cannot find the m2 module!");
135            }
136            boolean foundM1 = false;
137            for (RequiresDirective rd : ElementFilter.requiresIn(m2Module.getDirectives())) {
138                foundM1 |= rd.getDependency().getSimpleName().contentEquals("m1");
139            }
140            if (!foundM1) {
141                throw new AssertionError("Cannot find the dependency on m1 module!");
142            }
143            return false;
144        }
145
146        @Override
147        public SourceVersion getSupportedSourceVersion() {
148            return SourceVersion.latest();
149        }
150
151    }
152
153    @Test
154    public void testAddReadsUnnamedModule(Path base) throws Exception {
155        Path jar = prepareTestJar(base);
156
157        Path moduleSrc = base.resolve("module-src");
158        Path m1 = moduleSrc.resolve("m1");
159
160        Path classes = base.resolve("classes");
161
162        Files.createDirectories(classes);
163
164        tb.writeJavaFiles(m1,
165                          "module m1 { }",
166                          "package impl; public class Impl { api.Api api; }");
167
168        new JavacTask(tb)
169          .options("--class-path", jar.toString(),
170                   "--add-reads", "m1=ALL-UNNAMED",
171                   "-XDrawDiagnostics")
172          .outdir(classes)
173          .files(findJavaFiles(moduleSrc))
174          .run()
175          .writeAll();
176    }
177
178    @Test
179    public void testAddReadsUnnamedModulePackageConflict(Path base) throws Exception {
180        Path jar = prepareTestJar(base);
181
182        Path moduleSrc = base.resolve("module-src");
183        Path m1 = moduleSrc.resolve("m1");
184
185        Path classes = base.resolve("classes");
186
187        Files.createDirectories(classes);
188
189        tb.writeJavaFiles(m1,
190                          "module m1 { }",
191                          "package api; public class Api { public static void test() { } }",
192                          "package impl; public class Impl { { api.Api.test(); } }");
193
194        new JavacTask(tb)
195          .options("--class-path", jar.toString(),
196                   "--module-source-path", moduleSrc.toString(),
197                   "--add-reads", "m1=ALL-UNNAMED",
198                   "-XDrawDiagnostics")
199          .outdir(classes)
200          .files(m1.resolve("impl").resolve("Impl.java"))
201          .run()
202          .writeAll();
203    }
204
205    @Test
206    public void testAddReadsUnnamedToJavaBase(Path base) throws Exception {
207        Path jar = prepareTestJar(base);
208        Path src = base.resolve("src");
209        Path classes = base.resolve("classes");
210
211        Files.createDirectories(classes);
212
213        tb.writeJavaFiles(src,
214                          "package impl; public class Impl { api.Api a; }");
215
216        new JavacTask(tb)
217          .options("--class-path", jar.toString(),
218                   "--add-reads", "java.base=ALL-UNNAMED",
219                   "-Xmodule:java.base")
220          .outdir(classes)
221          .files(src.resolve("impl").resolve("Impl.java"))
222          .run()
223          .writeAll();
224    }
225
226    @Test
227    public void testAddReadsToJavaBase(Path base) throws Exception {
228        Path src = base.resolve("src");
229        Path classes = base.resolve("classes");
230
231        Files.createDirectories(classes);
232
233        tb.writeJavaFiles(src,
234                          "package impl; public class Impl { javax.swing.JButton b; }");
235
236        new JavacTask(tb)
237          .options("--add-modules", "java.desktop",
238                   "--add-reads", "java.base=java.desktop",
239                   "-Xmodule:java.base")
240          .outdir(classes)
241          .files(findJavaFiles(src))
242          .run()
243          .writeAll();
244    }
245
246    private Path prepareTestJar(Path base) throws Exception {
247        Path legacySrc = base.resolve("legacy-src");
248        tb.writeJavaFiles(legacySrc,
249                          "package api; public abstract class Api {}");
250        Path legacyClasses = base.resolve("legacy-classes");
251        Files.createDirectories(legacyClasses);
252
253        String log = new JavacTask(tb)
254                .options()
255                .outdir(legacyClasses)
256                .files(findJavaFiles(legacySrc))
257                .run()
258                .writeAll()
259                .getOutput(Task.OutputKind.DIRECT);
260
261        if (!log.isEmpty()) {
262            throw new Exception("unexpected output: " + log);
263        }
264
265        Path lib = base.resolve("lib");
266
267        Files.createDirectories(lib);
268
269        Path jar = lib.resolve("test-api-1.0.jar");
270
271        new JarTask(tb, jar)
272          .baseDir(legacyClasses)
273          .files("api/Api.class")
274          .run();
275
276        return jar;
277    }
278
279    @Test
280    public void testX(Path base) throws Exception {
281        Path src = base.resolve("src");
282        Path src_m1 = src.resolve("m1");
283        tb.writeJavaFiles(src_m1,
284                          "module m1 { provides java.lang.Runnable with impl.Impl; }",
285                          "package impl; public class Impl implements Runnable { public void run() { } }");
286        Path classes = base.resolve("classes");
287        tb.createDirectories(classes);
288
289        new JavacTask(tb)
290                .options("--module-source-path", src.toString())
291                .outdir(classes)
292                .files(findJavaFiles(src))
293                .run()
294                .writeAll();
295
296        Path unnamedSrc = base.resolve("unnamed-src");
297        Path unnamedClasses = base.resolve("unnamed-classes");
298
299        Files.createDirectories(unnamedClasses);
300
301        tb.writeJavaFiles(unnamedSrc,
302                          "package impl; public class Impl { }");
303
304        new JavacTask(tb)
305          .options("--add-reads", "m1=ALL-UNNAMED",
306                   "-Xmodule:m1",
307                   "--module-path", classes.toString())
308          .outdir(unnamedClasses)
309          .files(findJavaFiles(unnamedSrc))
310          .run()
311          .writeAll();
312    }
313
314    @Test
315    public void testAddSelf(Path base) throws Exception {
316        Path src = base.resolve("src");
317        Path src_m1 = src.resolve("m1");
318        tb.writeJavaFiles(src_m1,
319                          "module m1 { exports p1; }",
320                          "package p1; public class C1 { }");
321        Path classes = base.resolve("classes");
322        tb.createDirectories(classes);
323
324        new JavacTask(tb)
325                .options("--module-source-path", src.toString(),
326                         "--add-reads", "m1=m1")
327                .outdir(classes)
328                .files(findJavaFiles(src))
329                .run()
330                .writeAll();
331    }
332
333    @Test
334    public void testEmpty(Path base) throws Exception {
335        Path src = base.resolve("src");
336        tb.writeJavaFiles(src, "class Dummy { }");
337        Path classes = base.resolve("classes");
338        tb.createDirectories(classes);
339
340        testEmpty(src, classes, "--add-reads", "");
341        testEmpty(src, classes, "--add-reads=");
342    }
343
344    private void testEmpty(Path src, Path classes, String... options) throws Exception {
345        String log = new JavacTask(tb, Task.Mode.CMDLINE)
346                .options(options)
347                .outdir(classes)
348                .files(findJavaFiles(src))
349                .run(Task.Expect.FAIL)
350                .writeAll()
351                .getOutput(Task.OutputKind.DIRECT);
352
353        checkOutputContains(log,
354            "javac: no value for --add-reads option");
355    }
356
357    @Test
358    public void testEmptyItem(Path base) throws Exception {
359        Path src = base.resolve("src");
360        Path src_m1 = src.resolve("m1");
361        tb.writeJavaFiles(src_m1,
362                          "module m1 { exports p1; }",
363                          "package p1; public class C1 { }");
364        Path src_m2 = src.resolve("m2");
365        tb.writeJavaFiles(src_m2,
366                          "module m2 { }",
367                          "package p2; class C2 { }");
368        Path src_m3 = src.resolve("m3");
369        tb.writeJavaFiles(src_m3,
370                          "module m3 { }",
371                          "package p3; class C3 { p1.C1 c1; }");
372        Path classes = base.resolve("classes");
373        tb.createDirectories(classes);
374
375        testEmptyItem(src, classes, "m3=,m1");
376        testEmptyItem(src, classes, "m3=m1,,m2");
377        testEmptyItem(src, classes, "m3=m1,");
378    }
379
380    private void testEmptyItem(Path src, Path classes, String option) throws Exception {
381        new JavacTask(tb)
382                .options("--module-source-path", src.toString(),
383                         "--add-reads", option)
384                .outdir(classes)
385                .files(findJavaFiles(src))
386                .run()
387                .writeAll();
388    }
389
390    @Test
391    public void testEmptyList(Path base) throws Exception {
392        Path src = base.resolve("src");
393        Path src_m1 = src.resolve("m1");
394        tb.writeJavaFiles(src_m1,
395                          "module m1 { exports p1; }",
396                          "package p1; public class C1 { }");
397        Path src_m2 = src.resolve("m2");
398        tb.writeJavaFiles(src_m2,
399                          "module m2 { }",
400                          "package p2; class C2 { }");
401        Path src_m3 = src.resolve("m3");
402        tb.writeJavaFiles(src_m3,
403                          "module m3 { }",
404                          "package p3; class C3 { p1.C1 c1; }");
405        Path classes = base.resolve("classes");
406        tb.createDirectories(classes);
407
408        testEmptyList(src, classes, "m3=");
409        testEmptyList(src, classes, "m3=,");
410    }
411
412    private void testEmptyList(Path src, Path classes, String option) throws Exception {
413        String log = new JavacTask(tb, Task.Mode.CMDLINE)
414                .options("--module-source-path", src.toString(),
415                         "--add-reads", option)
416                .outdir(classes)
417                .files(findJavaFiles(src))
418                .run(Task.Expect.FAIL)
419                .writeAll()
420                .getOutput(Task.OutputKind.DIRECT);
421
422        checkOutputContains(log,
423            "javac: bad value for --add-reads option: '" + option + "'");
424    }
425
426    @Test
427    public void testMultipleAddReads_DifferentModules(Path base) throws Exception {
428        Path src = base.resolve("src");
429        Path src_m1 = src.resolve("m1");
430        tb.writeJavaFiles(src_m1,
431                          "module m1 { exports p1; }",
432                          "package p1; public class C1 { }");
433        Path src_m2 = src.resolve("m2");
434        tb.writeJavaFiles(src_m2,
435                          "module m2 { }",
436                          "package p2; class C2 { p1.C1 c1; }");
437        Path src_m3 = src.resolve("m3");
438        tb.writeJavaFiles(src_m3,
439                          "module m3 { }",
440                          "package p3; class C3 { p1.C1 c1; }");
441        Path classes = base.resolve("classes");
442        tb.createDirectories(classes);
443
444        new JavacTask(tb)
445                .options("--module-source-path", src.toString(),
446                         "--add-reads", "m2=m1",
447                         "--add-reads", "m3=m1")
448                .outdir(classes)
449                .files(findJavaFiles(src))
450                .run()
451                .writeAll();
452    }
453
454    @Test
455    public void testMultipleAddReads_SameModule(Path base) throws Exception {
456        Path src = base.resolve("src");
457        Path src_m1 = src.resolve("m1");
458        tb.writeJavaFiles(src_m1,
459                          "module m1 { exports p1; }",
460                          "package p1; public class C1 { }");
461        Path src_m2 = src.resolve("m2");
462        tb.writeJavaFiles(src_m2,
463                          "module m2 { exports p2; }",
464                          "package p2; public class C2 { }");
465        Path src_m3 = src.resolve("m3");
466        tb.writeJavaFiles(src_m3,
467                          "module m3 { }",
468                          "package p3; class C3 { p1.C1 c1; p2.C2 c2; }");
469        Path classes = base.resolve("classes");
470        tb.createDirectories(classes);
471
472        new JavacTask(tb)
473                .options("--module-source-path", src.toString(),
474                         "--add-reads", "m3=m1",
475                         "--add-reads", "m3=m2")
476                .outdir(classes)
477                .files(findJavaFiles(src))
478                .run()
479                .writeAll();
480    }
481
482    @Test
483    public void testDuplicateAddReads_SameOption(Path base) throws Exception {
484        Path src = base.resolve("src");
485        Path src_m1 = src.resolve("m1");
486        tb.writeJavaFiles(src_m1,
487                          "module m1 { exports p1; }",
488                          "package p1; public class C1 { }");
489        Path src_m2 = src.resolve("m2");
490        tb.writeJavaFiles(src_m2,
491                          "module m2 { exports p2; }",
492                          "package p2; class C2 { p1.C1 c1; }");
493        Path classes = base.resolve("classes");
494        tb.createDirectories(classes);
495
496        new JavacTask(tb)
497                .options("--module-source-path", src.toString(),
498                         "--add-reads", "m2=m1,m1")
499                .outdir(classes)
500                .files(findJavaFiles(src))
501                .run()
502                .writeAll();
503    }
504
505    @Test
506    public void testDuplicateAddReads_MultipleOptions(Path base) throws Exception {
507        Path src = base.resolve("src");
508        Path src_m1 = src.resolve("m1");
509        tb.writeJavaFiles(src_m1,
510                          "module m1 { exports p1; }",
511                          "package p1; public class C1 { }");
512        Path src_m2 = src.resolve("m2");
513        tb.writeJavaFiles(src_m2,
514                          "module m2 { }",
515                          "package p2; class C2 { p1.C1 c1; }");
516        Path classes = base.resolve("classes");
517        tb.createDirectories(classes);
518
519        new JavacTask(tb)
520                .options("--module-source-path", src.toString(),
521                         "--add-reads", "m2=m1",
522                         "--add-reads", "m2=m1")
523                .outdir(classes)
524                .files(findJavaFiles(src))
525                .run()
526                .writeAll();
527    }
528
529    @Test
530    public void testRepeatedAddReads(Path base) throws Exception {
531        Path src = base.resolve("src");
532        Path src_m1 = src.resolve("m1");
533        tb.writeJavaFiles(src_m1,
534                          "module m1 { exports p1; }",
535                          "package p1; public class C1 { }");
536        Path src_m2 = src.resolve("m2");
537        tb.writeJavaFiles(src_m2,
538                          "module m2 { exports p2; }",
539                          "package p2; public class C2 { }");
540        Path src_m3 = src.resolve("m3");
541        tb.writeJavaFiles(src_m3,
542                          "module m3 { }",
543                          "package p3; class C3 { p1.C1 c1; p2.C2 c2; }");
544        Path classes = base.resolve("classes");
545        tb.createDirectories(classes);
546
547        new JavacTask(tb)
548                .options("--module-source-path", src.toString(),
549                         "--add-reads", "m3=m1",
550                         "--add-reads", "m3=m2")
551                .outdir(classes)
552                .files(findJavaFiles(src))
553                .run()
554                .writeAll();
555    }
556
557    @Test
558    public void testNoEquals(Path base) throws Exception {
559        Path src = base.resolve("src");
560        tb.writeJavaFiles(src, "class Dummy { }");
561        Path classes = base.resolve("classes");
562        tb.createDirectories(classes);
563
564        String log = new JavacTask(tb, Task.Mode.CMDLINE)
565                .options("-XDrawDiagnostics",
566                         "--add-reads", "m1:m2")
567                .outdir(classes)
568                .files(findJavaFiles(src))
569                .run(Task.Expect.FAIL)
570                .writeAll()
571                .getOutput(Task.OutputKind.DIRECT);
572
573        checkOutputContains(log,
574            "javac: bad value for --add-reads option: 'm1:m2'");
575    }
576
577    @Test
578    public void testBadSourceName(Path base) throws Exception {
579        Path src = base.resolve("src");
580        tb.writeJavaFiles(src, "class Dummy { }");
581        Path classes = base.resolve("classes");
582        tb.createDirectories(classes);
583
584        String log = new JavacTask(tb)
585                .options("-XDrawDiagnostics",
586                         "--add-reads", "bad*Source=m2")
587                .outdir(classes)
588                .files(findJavaFiles(src))
589                .run()
590                .writeAll()
591                .getOutput(Task.OutputKind.DIRECT);
592
593        checkOutputContains(log,
594            "- compiler.warn.bad.name.for.option: --add-reads, bad*Source");
595    }
596
597    @Test
598    public void testBadTargetName(Path base) throws Exception {
599        Path src = base.resolve("src");
600        Path src_m1 = src.resolve("m1");
601        tb.writeJavaFiles(src_m1,
602                          "module m1 { }",
603                          "package p1; class C1 { }");
604        Path classes = base.resolve("classes");
605        tb.createDirectories(classes);
606
607        String log = new JavacTask(tb)
608                .options("-XDrawDiagnostics",
609                         "--add-reads", "m1=badTarget!")
610                .outdir(classes)
611                .files(findJavaFiles(src))
612                .run()
613                .writeAll()
614                .getOutput(Task.OutputKind.DIRECT);
615
616        checkOutputContains(log,
617            "- compiler.warn.bad.name.for.option: --add-reads, badTarget!");
618    }
619
620    @Test
621    public void testSourceNameNotFound(Path base) throws Exception {
622        Path src = base.resolve("src");
623        Path src_m1 = src.resolve("m1");
624        tb.writeJavaFiles(src_m1,
625                          "module m1 { exports p1; }",
626                          "package p1; public class C1 { }");
627        Path classes = base.resolve("classes");
628        tb.createDirectories(classes);
629
630        String log = new JavacTask(tb)
631                .options("-XDrawDiagnostics",
632                         "--add-reads", "missingSource=m1")
633                .outdir(classes)
634                .files(findJavaFiles(src))
635                .run()
636                .writeAll()
637                .getOutput(Task.OutputKind.DIRECT);
638
639        checkOutputContains(log,
640            "- compiler.warn.module.for.option.not.found: --add-reads, missingSource");
641    }
642
643    @Test
644    public void testTargetNameNotFound(Path base) throws Exception {
645        Path src = base.resolve("src");
646        Path src_m1 = src.resolve("m1");
647        tb.writeJavaFiles(src_m1,
648                          "module m1 { exports p1; }",
649                          "package p1; public class C1 { }");
650        Path classes = base.resolve("classes");
651        tb.createDirectories(classes);
652
653        String log = new JavacTask(tb)
654                .options("-XDrawDiagnostics",
655                         "--add-reads", "m1=missingTarget")
656                .outdir(classes)
657                .files(findJavaFiles(src))
658                .run()
659                .writeAll()
660                .getOutput(Task.OutputKind.DIRECT);
661
662        checkOutputContains(log,
663            "- compiler.warn.module.for.option.not.found: --add-reads, missingTarget");
664    }
665}
666