AutomaticModules.java revision 4215:abaedfca9e3e
1139749Simp/*
2135048Swpaul * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3135048Swpaul * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4135048Swpaul *
5135048Swpaul * This code is free software; you can redistribute it and/or modify it
6135048Swpaul * under the terms of the GNU General Public License version 2 only, as
7135048Swpaul * published by the Free Software Foundation.
8135048Swpaul *
9135048Swpaul * This code is distributed in the hope that it will be useful, but WITHOUT
10135048Swpaul * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11135048Swpaul * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12135048Swpaul * version 2 for more details (a copy is included in the LICENSE file that
13135048Swpaul * accompanied this code).
14135048Swpaul *
15135048Swpaul * You should have received a copy of the GNU General Public License version
16135048Swpaul * 2 along with this work; if not, write to the Free Software Foundation,
17135048Swpaul * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18135048Swpaul *
19135048Swpaul * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20135048Swpaul * or visit www.oracle.com if you need additional information or have any
21135048Swpaul * questions.
22135048Swpaul */
23135048Swpaul
24135048Swpaul/**
25135048Swpaul * @test
26135048Swpaul * @bug 8155026 8178011
27135048Swpaul * @summary Test automatic modules
28135048Swpaul * @library /tools/lib
29135048Swpaul * @modules
30135048Swpaul *      java.desktop
31135048Swpaul *      jdk.compiler/com.sun.tools.javac.api
32135048Swpaul *      jdk.compiler/com.sun.tools.javac.main
33135048Swpaul * @build toolbox.ToolBox toolbox.JavacTask toolbox.JarTask ModuleTestBase
34135048Swpaul * @run main AutomaticModules
35135048Swpaul */
36135048Swpaul
37178598Srajimport java.io.File;
38135048Swpaulimport java.nio.file.Files;
39135048Swpaulimport java.nio.file.Path;
40135048Swpaulimport java.util.Arrays;
41135048Swpaulimport java.util.List;
42135048Swpaulimport java.util.zip.ZipEntry;
43135048Swpaulimport java.util.zip.ZipOutputStream;
44135048Swpaul
45135048Swpaulimport toolbox.JarTask;
46135048Swpaulimport toolbox.JavacTask;
47135048Swpaulimport toolbox.Task;
48135048Swpaulimport toolbox.Task.Mode;
49135048Swpaul
50135048Swpaulpublic class AutomaticModules extends ModuleTestBase {
51135048Swpaul
52135048Swpaul    public static void main(String... args) throws Exception {
53135048Swpaul        AutomaticModules t = new AutomaticModules();
54135048Swpaul        t.runTests();
55135048Swpaul    }
56135048Swpaul
57135048Swpaul    @Test
58135048Swpaul    public void testSimple(Path base) throws Exception {
59135048Swpaul        Path legacySrc = base.resolve("legacy-src");
60213893Smarius        tb.writeJavaFiles(legacySrc,
61135048Swpaul                          "package api; import java.awt.event.ActionListener; public abstract class Api implements ActionListener {}");
62135048Swpaul        Path legacyClasses = base.resolve("legacy-classes");
63135048Swpaul        Files.createDirectories(legacyClasses);
64135048Swpaul
65135048Swpaul        String log = new JavacTask(tb)
66135048Swpaul                .options()
67135048Swpaul                .outdir(legacyClasses)
68135048Swpaul                .files(findJavaFiles(legacySrc))
69135048Swpaul                .run()
70135048Swpaul                .writeAll()
71135048Swpaul                .getOutput(Task.OutputKind.DIRECT);
72135048Swpaul
73135048Swpaul        if (!log.isEmpty()) {
74135048Swpaul            throw new Exception("unexpected output: " + log);
75135048Swpaul        }
76135048Swpaul
77135048Swpaul        Path modulePath = base.resolve("module-path");
78135048Swpaul
79135048Swpaul        Files.createDirectories(modulePath);
80135048Swpaul
81135048Swpaul        Path jar = modulePath.resolve("test-api-1.0.jar");
82135048Swpaul
83135048Swpaul        new JarTask(tb, jar)
84135048Swpaul          .baseDir(legacyClasses)
85135048Swpaul          .files("api/Api.class")
86135048Swpaul          .run();
87135048Swpaul
88164827Smarius        Path moduleSrc = base.resolve("module-src");
89221407Smarius        Path m1 = moduleSrc.resolve("m1x");
90221407Smarius
91221407Smarius        Path classes = base.resolve("classes");
92221407Smarius
93221407Smarius        Files.createDirectories(classes);
94221407Smarius
95221407Smarius        tb.writeJavaFiles(m1,
96164827Smarius                          "module m1x { requires test.api; requires java.desktop; }",
97164827Smarius                          "package impl; public class Impl { public void e(api.Api api) { api.actionPerformed(null); } }");
98164827Smarius
99221407Smarius        new JavacTask(tb)
100221407Smarius                .options("--module-source-path", moduleSrc.toString(), "--module-path", modulePath.toString())
101221407Smarius                .outdir(classes)
102221407Smarius                .files(findJavaFiles(moduleSrc))
103221407Smarius                .run()
104221407Smarius                .writeAll();
105135048Swpaul    }
106150763Simp
107135048Swpaul    @Test
108135048Swpaul    public void testUnnamedModule(Path base) throws Exception {
109164827Smarius        Path legacySrc = base.resolve("legacy-src");
110135048Swpaul        tb.writeJavaFiles(legacySrc,
111135048Swpaul                          "package api; public abstract class Api { public void run(CharSequence str) { } private void run(base.Base base) { } }",
112135048Swpaul                          "package base; public interface Base { public void run(); }");
113150763Simp        Path legacyClasses = base.resolve("legacy-classes");
114135048Swpaul        Files.createDirectories(legacyClasses);
115135048Swpaul
116221407Smarius        String log = new JavacTask(tb)
117221407Smarius                .options()
118164705Smarius                .outdir(legacyClasses)
119135048Swpaul                .files(findJavaFiles(legacySrc))
120135048Swpaul                .run()
121135048Swpaul                .writeAll()
122150763Simp                .getOutput(Task.OutputKind.DIRECT);
123135048Swpaul
124135048Swpaul        if (!log.isEmpty()) {
125135048Swpaul            throw new Exception("unexpected output: " + log);
126135048Swpaul        }
127135048Swpaul
128135048Swpaul        Path modulePath = base.resolve("module-path");
129135048Swpaul
130135048Swpaul        Files.createDirectories(modulePath);
131135048Swpaul
132135048Swpaul        Path apiJar = modulePath.resolve("test-api-1.0.jar");
133135048Swpaul
134135048Swpaul        new JarTask(tb, apiJar)
135135048Swpaul          .baseDir(legacyClasses)
136135048Swpaul          .files("api/Api.class")
137135048Swpaul          .run();
138135048Swpaul
139135048Swpaul        Path baseJar = base.resolve("base.jar");
140135048Swpaul
141135048Swpaul        new JarTask(tb, baseJar)
142135048Swpaul          .baseDir(legacyClasses)
143135048Swpaul          .files("base/Base.class")
144135048Swpaul          .run();
145135048Swpaul
146135048Swpaul        Path moduleSrc = base.resolve("module-src");
147135048Swpaul        Path m1 = moduleSrc.resolve("m1x");
148135048Swpaul
149215297Smarius        Path classes = base.resolve("classes");
150135048Swpaul
151135048Swpaul        Files.createDirectories(classes);
152135048Swpaul
153135048Swpaul        tb.writeJavaFiles(m1,
154135048Swpaul                          "module m1x { requires test.api; }",
155135048Swpaul                          "package impl; public class Impl { public void e(api.Api api) { api.run(\"\"); } }");
156135048Swpaul
157135048Swpaul        new JavacTask(tb)
158135048Swpaul                .options("--module-source-path", moduleSrc.toString(), "--module-path", modulePath.toString(), "--class-path", baseJar.toString())
159135048Swpaul                .outdir(classes)
160217413Smarius                .files(findJavaFiles(moduleSrc))
161135048Swpaul                .run()
162135048Swpaul                .writeAll();
163217413Smarius    }
164135048Swpaul
165135048Swpaul    @Test
166217413Smarius    public void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception {
167217413Smarius        Path automaticSrc = base.resolve("automaticSrc");
168217413Smarius        tb.writeJavaFiles(automaticSrc, "package api; public class Api {}");
169217413Smarius        Path automaticClasses = base.resolve("automaticClasses");
170217413Smarius        tb.createDirectories(automaticClasses);
171217413Smarius
172217413Smarius        String automaticLog = new JavacTask(tb)
173217413Smarius                                .outdir(automaticClasses)
174217413Smarius                                .files(findJavaFiles(automaticSrc))
175135048Swpaul                                .run()
176135048Swpaul                                .writeAll()
177135048Swpaul                                .getOutput(Task.OutputKind.DIRECT);
178135048Swpaul
179215297Smarius        if (!automaticLog.isEmpty())
180135048Swpaul            throw new Exception("expected output not found: " + automaticLog);
181135048Swpaul
182135048Swpaul        Path modulePath = base.resolve("module-path");
183135048Swpaul
184135048Swpaul        Files.createDirectories(modulePath);
185135048Swpaul
186135048Swpaul        Path automaticJar = modulePath.resolve("automatic-1.0.jar");
187135048Swpaul
188135048Swpaul        new JarTask(tb, automaticJar)
189135048Swpaul          .baseDir(automaticClasses)
190135048Swpaul          .files("api/Api.class")
191135048Swpaul          .run();
192135048Swpaul
193135048Swpaul        Path depSrc = base.resolve("depSrc");
194135048Swpaul        Path depClasses = base.resolve("depClasses");
195135048Swpaul
196135048Swpaul        Files.createDirectories(depSrc);
197135048Swpaul        Files.createDirectories(depClasses);
198135048Swpaul
199135048Swpaul        tb.writeJavaFiles(depSrc,
200135048Swpaul                          "module m1x { requires transitive automatic; }",
201135048Swpaul                          "package dep; public class Dep { api.Api api; }");
202135048Swpaul
203135048Swpaul        new JavacTask(tb)
204135048Swpaul                .options("--module-path", modulePath.toString())
205135048Swpaul                .outdir(depClasses)
206135048Swpaul                .files(findJavaFiles(depSrc))
207135048Swpaul                .run()
208183488Syongari                .writeAll();
209183488Syongari
210183488Syongari        Path moduleJar = modulePath.resolve("m1x.jar");
211135048Swpaul
212183489Syongari        new JarTask(tb, moduleJar)
213135048Swpaul          .baseDir(depClasses)
214183489Syongari          .files("module-info.class", "dep/Dep.class")
215135048Swpaul          .run();
216164705Smarius
217135048Swpaul        Path testSrc = base.resolve("testSrc");
218135048Swpaul        Path testClasses = base.resolve("testClasses");
219183490Syongari
220135048Swpaul        Files.createDirectories(testSrc);
221135048Swpaul        Files.createDirectories(testClasses);
222135048Swpaul
223221407Smarius        tb.writeJavaFiles(testSrc,
224135048Swpaul                          "module m2x { requires automatic; }",
225135048Swpaul                          "package test; public class Test { }");
226135048Swpaul
227135048Swpaul        new JavacTask(tb)
228135048Swpaul                .options("--module-path", modulePath.toString())
229164705Smarius                .outdir(testClasses)
230135048Swpaul                .files(findJavaFiles(testSrc))
231135048Swpaul                .run()
232135048Swpaul                .writeAll();
233135048Swpaul    }
234135048Swpaul
235135048Swpaul    @Test
236135048Swpaul    public void testAutomaticAndNamedModules(Path base) throws Exception {
237135048Swpaul        Path modulePath = base.resolve("module-path");
238135048Swpaul
239150763Simp        Files.createDirectories(modulePath);
240135048Swpaul
241135048Swpaul        for (char c : new char[] {'A', 'B'}) {
242135048Swpaul            Path automaticSrc = base.resolve("automaticSrc" + c);
243135048Swpaul            tb.writeJavaFiles(automaticSrc, "package api" + c + "; public class Api {}");
244135048Swpaul            Path automaticClasses = base.resolve("automaticClasses" + c);
245135048Swpaul            tb.createDirectories(automaticClasses);
246135048Swpaul
247135048Swpaul            String automaticLog = new JavacTask(tb)
248135048Swpaul                                    .outdir(automaticClasses)
249135048Swpaul                                    .files(findJavaFiles(automaticSrc))
250135048Swpaul                                    .run()
251135048Swpaul                                    .writeAll()
252135048Swpaul                                    .getOutput(Task.OutputKind.DIRECT);
253135048Swpaul
254135048Swpaul            if (!automaticLog.isEmpty())
255135048Swpaul                throw new Exception("expected output not found: " + automaticLog);
256135048Swpaul
257135048Swpaul            Path automaticJar = modulePath.resolve("automatic" + c + "-1.0.jar");
258135048Swpaul
259135048Swpaul            new JarTask(tb, automaticJar)
260135048Swpaul              .baseDir(automaticClasses)
261135048Swpaul              .files("api" + c + "/Api.class")
262135048Swpaul              .run();
263135048Swpaul        }
264135048Swpaul
265135048Swpaul        Path moduleSrc = base.resolve("module-src");
266135048Swpaul
267135048Swpaul        tb.writeJavaFiles(moduleSrc.resolve("m1x"),
268135048Swpaul                          "module m1x { requires static automaticA; }",
269135048Swpaul                          "package impl; public class Impl { apiA.Api a; apiB.Api b; m2x.M2 m;}");
270135048Swpaul
271135048Swpaul        tb.writeJavaFiles(moduleSrc.resolve("m2x"),
272135048Swpaul                          "module m2x { exports m2x; }",
273135048Swpaul                          "package m2x; public class M2 { }");
274135048Swpaul
275135048Swpaul        Path classes = base.resolve("classes");
276135048Swpaul
277135048Swpaul        Files.createDirectories(classes);
278135048Swpaul
279135048Swpaul        List<String> log = new JavacTask(tb)
280135048Swpaul                .options("--module-source-path", moduleSrc.toString(),
281135048Swpaul                         "--module-path", modulePath.toString(),
282135048Swpaul                         "--add-modules", "automaticB",
283221407Smarius                         "-XDrawDiagnostics")
284183491Syongari                .outdir(classes)
285183491Syongari                .files(findJavaFiles(moduleSrc))
286215297Smarius                .run(Task.Expect.FAIL)
287215297Smarius                .writeAll()
288215297Smarius                .getOutputLines(Task.OutputKind.DIRECT);
289215297Smarius
290135048Swpaul        List<String> expected = Arrays.asList("Impl.java:1:59: compiler.err.package.not.visible: m2x, (compiler.misc.not.def.access.does.not.read: m1x, m2x, m2x)",
291135048Swpaul                                              "1 error");
292135048Swpaul
293135048Swpaul        if (!expected.equals(log)) {
294135048Swpaul            throw new Exception("expected output not found: " + log);
295164830Smarius        }
296135048Swpaul
297135048Swpaul        log = new JavacTask(tb)
298135048Swpaul                .options("--module-source-path", moduleSrc.toString(),
299135048Swpaul                         "--module-path", modulePath.toString(),
300135048Swpaul                         "-XDrawDiagnostics")
301135048Swpaul                .outdir(classes)
302135048Swpaul                .files(findJavaFiles(moduleSrc))
303135048Swpaul                .run(Task.Expect.FAIL)
304135048Swpaul                .writeAll()
305135048Swpaul                .getOutputLines(Task.OutputKind.DIRECT);
306135048Swpaul
307135048Swpaul        expected = Arrays.asList("Impl.java:1:59: compiler.err.package.not.visible: m2x, (compiler.misc.not.def.access.does.not.read: m1x, m2x, m2x)",
308135048Swpaul                                 "1 error");
309135048Swpaul
310170365Syongari        if (!expected.equals(log)) {
311135048Swpaul            throw new Exception("expected output not found: " + log);
312135048Swpaul        }
313135048Swpaul    }
314135048Swpaul
315135048Swpaul    @Test
316170365Syongari    public void testWithTrailingVersion(Path base) throws Exception {
317170365Syongari        Path legacySrc = base.resolve("legacy-src");
318170365Syongari        tb.writeJavaFiles(legacySrc,
319170365Syongari                          "package api; public class Api {}");
320170365Syongari        Path legacyClasses = base.resolve("legacy-classes");
321170365Syongari        Files.createDirectories(legacyClasses);
322170365Syongari
323170365Syongari        String log = new JavacTask(tb)
324170365Syongari                .options()
325170365Syongari                .outdir(legacyClasses)
326170365Syongari                .files(findJavaFiles(legacySrc))
327170365Syongari                .run()
328170365Syongari                .writeAll()
329170365Syongari                .getOutput(Task.OutputKind.DIRECT);
330170365Syongari
331170365Syongari        if (!log.isEmpty()) {
332135048Swpaul            throw new Exception("unexpected output: " + log);
333221407Smarius        }
334221407Smarius
335135048Swpaul        Path modulePath = base.resolve("module-path");
336135048Swpaul
337135048Swpaul        Files.createDirectories(modulePath);
338135048Swpaul
339135048Swpaul        Path jar = modulePath.resolve("test1.jar");
340135048Swpaul
341135048Swpaul        new JarTask(tb, jar)
342135048Swpaul          .baseDir(legacyClasses)
343135048Swpaul          .files("api/Api.class")
344135048Swpaul          .run();
345135048Swpaul
346135048Swpaul        Path moduleSrc = base.resolve("module-src");
347135048Swpaul        Path m = moduleSrc.resolve("m");
348135048Swpaul
349135048Swpaul        Path classes = base.resolve("classes");
350135048Swpaul
351135048Swpaul        Files.createDirectories(classes);
352135048Swpaul
353135048Swpaul        tb.writeJavaFiles(m,
354135048Swpaul                          "module m { requires test1; }",
355221407Smarius                          "package impl; public class Impl { public void e(api.Api api) { } }");
356221407Smarius
357135048Swpaul        new JavacTask(tb)
358135048Swpaul                .options("--module-source-path", moduleSrc.toString(), "--module-path", modulePath.toString())
359135048Swpaul                .outdir(classes)
360135048Swpaul                .files(findJavaFiles(moduleSrc))
361135048Swpaul                .run()
362135048Swpaul                .writeAll();
363135048Swpaul    }
364135048Swpaul
365135048Swpaul    @Test
366135048Swpaul    public void testMultipleAutomatic(Path base) throws Exception {
367135048Swpaul        Path modulePath = base.resolve("module-path");
368135048Swpaul
369135048Swpaul        Files.createDirectories(modulePath);
370221407Smarius
371221407Smarius        for (char c : new char[] {'A', 'B'}) {
372221407Smarius            Path automaticSrc = base.resolve("automaticSrc" + c);
373170365Syongari            tb.writeJavaFiles(automaticSrc, "package api" + c + "; public class Api {}");
374135048Swpaul            Path automaticClasses = base.resolve("automaticClasses" + c);
375135048Swpaul            tb.createDirectories(automaticClasses);
376135048Swpaul
377135048Swpaul            String automaticLog = new JavacTask(tb)
378135048Swpaul                                    .outdir(automaticClasses)
379135048Swpaul                                    .files(findJavaFiles(automaticSrc))
380                                    .run()
381                                    .writeAll()
382                                    .getOutput(Task.OutputKind.DIRECT);
383
384            if (!automaticLog.isEmpty())
385                throw new Exception("expected output not found: " + automaticLog);
386
387            Path automaticJar = modulePath.resolve("automatic" + c + "-1.0.jar");
388
389            new JarTask(tb, automaticJar)
390              .baseDir(automaticClasses)
391              .files("api" + c + "/Api.class")
392              .run();
393        }
394
395        Path src = base.resolve("src");
396
397        tb.writeJavaFiles(src.resolve("m1x"),
398                          "package impl; public class Impl { apiA.Api a; apiB.Api b; }");
399
400        Path classes = base.resolve("classes");
401
402        Files.createDirectories(classes);
403
404        List<String> log = new JavacTask(tb)
405                .options("--module-path", modulePath.toString(),
406                         "-XDrawDiagnostics")
407                .outdir(classes)
408                .files(findJavaFiles(src))
409                .run(Task.Expect.FAIL)
410                .writeAll()
411                .getOutputLines(Task.OutputKind.DIRECT);
412
413        List<String> expected = Arrays.asList("Impl.java:1:35: compiler.err.package.not.visible: apiA, (compiler.misc.not.def.access.does.not.read.from.unnamed: apiA, automaticA)",
414                                              "Impl.java:1:47: compiler.err.package.not.visible: apiB, (compiler.misc.not.def.access.does.not.read.from.unnamed: apiB, automaticB)",
415                                              "2 errors");
416
417        if (!expected.equals(log)) {
418            throw new Exception("expected output not found: " + log);
419        }
420
421        new JavacTask(tb)
422                .options("--module-path", modulePath.toString(),
423                         "--add-modules", "automaticA",
424                         "-XDrawDiagnostics")
425                .outdir(classes)
426                .files(findJavaFiles(src))
427                .run()
428                .writeAll();
429    }
430
431    @Test
432    public void testLintRequireAutomatic(Path base) throws Exception {
433        Path modulePath = base.resolve("module-path");
434
435        Files.createDirectories(modulePath);
436
437        for (char c : new char[] {'A', 'B'}) {
438            Path automaticSrc = base.resolve("automaticSrc" + c);
439            tb.writeJavaFiles(automaticSrc, "package api" + c + "; public class Api {}");
440            Path automaticClasses = base.resolve("automaticClasses" + c);
441            tb.createDirectories(automaticClasses);
442
443            String automaticLog = new JavacTask(tb)
444                                    .outdir(automaticClasses)
445                                    .files(findJavaFiles(automaticSrc))
446                                    .run()
447                                    .writeAll()
448                                    .getOutput(Task.OutputKind.DIRECT);
449
450            if (!automaticLog.isEmpty())
451                throw new Exception("expected output not found: " + automaticLog);
452
453            Path automaticJar = modulePath.resolve("automatic" + c + "-1.0.jar");
454
455            new JarTask(tb, automaticJar)
456              .baseDir(automaticClasses)
457              .files("api" + c + "/Api.class")
458              .run();
459        }
460
461        Path src = base.resolve("src");
462
463        tb.writeJavaFiles(src,
464                          "module m1x {\n" +
465                          "    requires transitive automaticA;\n" +
466                          "    requires automaticB;\n" +
467                          "}");
468
469        Path classes = base.resolve("classes");
470
471        Files.createDirectories(classes);
472
473        List<String> expected;
474        List<String> log;
475
476        log = new JavacTask(tb)
477            .options("--source-path", src.toString(),
478                     "--module-path", modulePath.toString(),
479                     "-XDrawDiagnostics",
480                     "-Werror")
481            .outdir(classes)
482            .files(findJavaFiles(src))
483            .run(Task.Expect.FAIL)
484            .writeAll()
485            .getOutputLines(Task.OutputKind.DIRECT);
486
487        expected = Arrays.asList("module-info.java:2:25: compiler.warn.requires.transitive.automatic",
488                                 "- compiler.err.warnings.and.werror",
489                                 "1 error",
490                                 "1 warning");
491
492        if (!expected.equals(log)) {
493            throw new Exception("expected output not found: " + log);
494        }
495
496        log = new JavacTask(tb)
497            .options("--source-path", src.toString(),
498                     "--module-path", modulePath.toString(),
499                     "-Xlint:requires-automatic",
500                     "-XDrawDiagnostics",
501                     "-Werror")
502            .outdir(classes)
503            .files(findJavaFiles(src))
504            .run(Task.Expect.FAIL)
505            .writeAll()
506            .getOutputLines(Task.OutputKind.DIRECT);
507
508        expected = Arrays.asList("module-info.java:2:25: compiler.warn.requires.transitive.automatic",
509                                 "module-info.java:3:14: compiler.warn.requires.automatic",
510                                 "- compiler.err.warnings.and.werror",
511                                 "1 error",
512                                 "2 warnings");
513
514        if (!expected.equals(log)) {
515            throw new Exception("expected output not found: " + log);
516        }
517
518        log = new JavacTask(tb)
519            .options("--source-path", src.toString(),
520                     "--module-path", modulePath.toString(),
521                     "-Xlint:-requires-transitive-automatic,requires-automatic",
522                     "-XDrawDiagnostics",
523                     "-Werror")
524            .outdir(classes)
525            .files(findJavaFiles(src))
526            .run(Task.Expect.FAIL)
527            .writeAll()
528            .getOutputLines(Task.OutputKind.DIRECT);
529
530        expected = Arrays.asList("module-info.java:2:25: compiler.warn.requires.automatic",
531                                 "module-info.java:3:14: compiler.warn.requires.automatic",
532                                 "- compiler.err.warnings.and.werror",
533                                 "1 error",
534                                 "2 warnings");
535
536        if (!expected.equals(log)) {
537            throw new Exception("expected output not found: " + log);
538        }
539
540        new JavacTask(tb)
541            .options("--source-path", src.toString(),
542                     "--module-path", modulePath.toString(),
543                     "-Xlint:-requires-transitive-automatic",
544                     "-XDrawDiagnostics",
545                     "-Werror")
546            .outdir(classes)
547            .files(findJavaFiles(src))
548            .run(Task.Expect.SUCCESS)
549            .writeAll()
550            .getOutputLines(Task.OutputKind.DIRECT);
551
552        tb.writeJavaFiles(src,
553                          "@SuppressWarnings(\"requires-transitive-automatic\")\n" +
554                          "module m1x {\n" +
555                          "    requires transitive automaticA;\n" +
556                          "    requires automaticB;\n" +
557                          "}");
558
559        new JavacTask(tb)
560            .options("--source-path", src.toString(),
561                     "--module-path", modulePath.toString(),
562                     "-XDrawDiagnostics",
563                     "-Werror")
564            .outdir(classes)
565            .files(findJavaFiles(src))
566            .run(Task.Expect.SUCCESS)
567            .writeAll()
568            .getOutputLines(Task.OutputKind.DIRECT);
569
570        log = new JavacTask(tb)
571            .options("--source-path", src.toString(),
572                     "--module-path", modulePath.toString(),
573                     "-Xlint:requires-automatic",
574                     "-XDrawDiagnostics",
575                     "-Werror")
576            .outdir(classes)
577            .files(findJavaFiles(src))
578            .run(Task.Expect.FAIL)
579            .writeAll()
580            .getOutputLines(Task.OutputKind.DIRECT);
581
582        expected = Arrays.asList("module-info.java:3:25: compiler.warn.requires.automatic",
583                                 "module-info.java:4:14: compiler.warn.requires.automatic",
584                                 "- compiler.err.warnings.and.werror",
585                                 "1 error",
586                                 "2 warnings");
587
588        if (!expected.equals(log)) {
589            throw new Exception("expected output not found: " + log);
590        }
591
592        tb.writeJavaFiles(src,
593                          "@SuppressWarnings(\"requires-automatic\")\n" +
594                          "module m1x {\n" +
595                          "    requires transitive automaticA;\n" +
596                          "    requires automaticB;\n" +
597                          "}");
598
599        log = new JavacTask(tb)
600            .options("--source-path", src.toString(),
601                     "--module-path", modulePath.toString(),
602                     "-Xlint:requires-automatic",
603                     "-XDrawDiagnostics",
604                     "-Werror")
605            .outdir(classes)
606            .files(findJavaFiles(src))
607            .run(Task.Expect.FAIL)
608            .writeAll()
609            .getOutputLines(Task.OutputKind.DIRECT);
610
611        expected = Arrays.asList("module-info.java:3:25: compiler.warn.requires.transitive.automatic",
612                                 "- compiler.err.warnings.and.werror",
613                                 "1 error",
614                                 "1 warning");
615
616        if (!expected.equals(log)) {
617            throw new Exception("expected output not found: " + log);
618        }
619    }
620
621    @Test
622    public void testAutomaticModuleNameCorrect(Path base) throws Exception {
623        Path modulePath = base.resolve("module-path");
624
625        Files.createDirectories(modulePath);
626
627        Path automaticSrc = base.resolve("automaticSrc");
628        tb.writeJavaFiles(automaticSrc, "package api; public class Api {}");
629        Path automaticClasses = base.resolve("automaticClasses");
630        tb.createDirectories(automaticClasses);
631
632        String automaticLog = new JavacTask(tb)
633                                .outdir(automaticClasses)
634                                .files(findJavaFiles(automaticSrc))
635                                .run()
636                                .writeAll()
637                                .getOutput(Task.OutputKind.DIRECT);
638
639        if (!automaticLog.isEmpty())
640            throw new Exception("expected output not found: " + automaticLog);
641
642        Path automaticJar = modulePath.resolve("automatic-1.0.jar");
643
644        new JarTask(tb, automaticJar)
645          .baseDir(automaticClasses)
646          .files("api/Api.class")
647          .manifest("Automatic-Module-Name: custom.module.name\n\n")
648          .run();
649
650        Path src = base.resolve("src");
651
652        tb.writeJavaFiles(src,
653                          "module m { requires custom.module.name; }",
654                          "package impl; public class Impl { api.Api a; }");
655
656        Path classes = base.resolve("classes");
657
658        Files.createDirectories(classes);
659
660        new JavacTask(tb)
661                .options("--module-path", modulePath.toString(),
662                         "-XDrawDiagnostics")
663                .outdir(classes)
664                .files(findJavaFiles(src))
665                .run(Task.Expect.SUCCESS)
666                .writeAll()
667                .getOutputLines(Task.OutputKind.DIRECT);
668
669        tb.writeJavaFiles(src,
670                          "module m { requires automatic; }");
671
672        List<String> log = new JavacTask(tb)
673                .options("--module-path", modulePath.toString(),
674                         "-XDrawDiagnostics")
675                .outdir(classes)
676                .files(findJavaFiles(src))
677                .run(Task.Expect.FAIL)
678                .writeAll()
679                .getOutputLines(Task.OutputKind.DIRECT);
680
681        List<String> expected =
682                Arrays.asList("module-info.java:1:21: compiler.err.module.not.found: automatic",
683                              "1 error");
684
685        if (!expected.equals(log)) {
686            throw new Exception("expected output not found: " + log);
687        }
688    }
689
690    @Test
691    public void testAutomaticModuleNameIncorrect(Path base) throws Exception {
692        for (String name : new String[] {"", "999", "foo.class", "foo._"}) {
693            if (Files.isDirectory(base)) {
694                tb.cleanDirectory(base);
695            }
696            Path modulePath = base.resolve("module-path");
697
698            Files.createDirectories(modulePath);
699
700            Path automaticSrc = base.resolve("automaticSrc");
701            tb.writeJavaFiles(automaticSrc, "package api; public class Api {}");
702            Path automaticClasses = base.resolve("automaticClasses");
703            tb.createDirectories(automaticClasses);
704
705            String automaticLog = new JavacTask(tb)
706                                    .outdir(automaticClasses)
707                                    .files(findJavaFiles(automaticSrc))
708                                    .run()
709                                    .writeAll()
710                                    .getOutput(Task.OutputKind.DIRECT);
711
712            if (!automaticLog.isEmpty())
713                throw new Exception("expected output not found: " + automaticLog);
714
715            Path automaticJar = modulePath.resolve("automatic-1.0.jar");
716
717            new JarTask(tb, automaticJar)
718              .baseDir(automaticClasses)
719              .files("api/Api.class")
720              .manifest("Automatic-Module-Name: " + name + "\n\n")
721              .run();
722
723            Path src = base.resolve("src");
724
725            tb.writeJavaFiles(src,
726                              "package impl; public class Impl { api.Api a; }");
727
728            Path classes = base.resolve("classes");
729
730            Files.createDirectories(classes);
731
732            List<String> log = new JavacTask(tb, Mode.CMDLINE)
733                    .options("--module-path", modulePath.toString(),
734                             "--add-modules", "ALL-MODULE-PATH",
735                             "-XDrawDiagnostics")
736                    .outdir(classes)
737                    .files(findJavaFiles(src))
738                    .run(Task.Expect.FAIL)
739                    .writeAll()
740                    .getOutputLines(Task.OutputKind.DIRECT);
741
742            List<String> expected =
743                    Arrays.asList("- compiler.err.locn.cant.get.module.name.for.jar: " +
744                                      "testAutomaticModuleNameIncorrect/module-path/automatic-1.0.jar".replace("/", File.separator),
745                                  "1 error");
746
747            if (!expected.equals(log)) {
748                throw new Exception("expected output not found: " + log);
749            }
750        }
751    }
752
753    @Test
754    public void testAutomaticModuleNameBroken(Path base) throws Exception {
755        Path modulePath = base.resolve("module-path");
756
757        Files.createDirectories(modulePath);
758
759        Path automaticSrc = base.resolve("automaticSrc");
760        tb.writeJavaFiles(automaticSrc, "package api; public class Api {}");
761        Path automaticClasses = base.resolve("automaticClasses");
762        tb.createDirectories(automaticClasses);
763
764        String automaticLog = new JavacTask(tb)
765                                .outdir(automaticClasses)
766                                .files(findJavaFiles(automaticSrc))
767                                .run()
768                                .writeAll()
769                                .getOutput(Task.OutputKind.DIRECT);
770
771        if (!automaticLog.isEmpty())
772            throw new Exception("expected output not found: " + automaticLog);
773
774        Path automaticJar = modulePath.resolve("automatic-1.0.jar");
775
776        try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(automaticJar))) {
777            out.putNextEntry(new ZipEntry("api/Api.class"));
778            Files.copy(automaticClasses.resolve("api").resolve("Api.class"), out);
779        }
780
781        Path src = base.resolve("src");
782
783        tb.writeJavaFiles(src,
784                          "module m { requires automatic; }",
785                          "package impl; public class Impl { api.Api a; }");
786
787        Path classes = base.resolve("classes");
788
789        Files.createDirectories(classes);
790
791        new JavacTask(tb)
792                .options("--module-path", modulePath.toString(),
793                         "-XDrawDiagnostics")
794                .outdir(classes)
795                .files(findJavaFiles(src))
796                .run(Task.Expect.SUCCESS)
797                .writeAll()
798                .getOutputLines(Task.OutputKind.DIRECT);
799
800        tb.writeJavaFiles(src,
801                          "module m { requires custom.module.name; }");
802
803        List<String> log = new JavacTask(tb)
804                .options("--module-path", modulePath.toString(),
805                         "-XDrawDiagnostics")
806                .outdir(classes)
807                .files(findJavaFiles(src))
808                .run(Task.Expect.FAIL)
809                .writeAll()
810                .getOutputLines(Task.OutputKind.DIRECT);
811
812        List<String> expected =
813                Arrays.asList("module-info.java:1:34: compiler.err.module.not.found: custom.module.name",
814                              "1 error");
815
816        if (!expected.equals(log)) {
817            throw new Exception("expected output not found: " + log);
818        }
819    }
820
821}
822