AutomaticModules.java revision 3792:d516975e8110
153537Sbrian/*
280728Sbrian * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
353537Sbrian * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
453537Sbrian *
553537Sbrian * This code is free software; you can redistribute it and/or modify it
653537Sbrian * under the terms of the GNU General Public License version 2 only, as
753537Sbrian * published by the Free Software Foundation.
853537Sbrian *
953537Sbrian * This code is distributed in the hope that it will be useful, but WITHOUT
1053537Sbrian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1153537Sbrian * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1253537Sbrian * version 2 for more details (a copy is included in the LICENSE file that
1353537Sbrian * accompanied this code).
1453537Sbrian *
1553537Sbrian * You should have received a copy of the GNU General Public License version
1653537Sbrian * 2 along with this work; if not, write to the Free Software Foundation,
1753537Sbrian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1853537Sbrian *
1953537Sbrian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2053537Sbrian * or visit www.oracle.com if you need additional information or have any
2153537Sbrian * questions.
2253537Sbrian */
2353537Sbrian
2453537Sbrian/**
2553537Sbrian * @test
2653537Sbrian * @bug 8155026
2753537Sbrian * @summary Test automatic modules
2853537Sbrian * @library /tools/lib
2953537Sbrian * @modules
3079529Sru *      java.desktop
3153537Sbrian *      jdk.compiler/com.sun.tools.javac.api
3253537Sbrian *      jdk.compiler/com.sun.tools.javac.main
3353537Sbrian * @build toolbox.ToolBox toolbox.JavacTask toolbox.JarTask ModuleTestBase
3453537Sbrian * @run main AutomaticModules
3568949Sru */
3670227Sru
3753609Sbrianimport java.nio.file.Files;
3853537Sbrianimport java.nio.file.Path;
3981251Sruimport java.util.Arrays;
4066602Sbrianimport java.util.List;
4153537Sbrian
4253537Sbrianimport toolbox.JarTask;
4353537Sbrianimport toolbox.JavacTask;
4453537Sbrianimport toolbox.Task;
4553537Sbrian
4699500Scharnierpublic class AutomaticModules extends ModuleTestBase {
4753537Sbrian
4853537Sbrian    public static void main(String... args) throws Exception {
4986783Sru        AutomaticModules t = new AutomaticModules();
5086783Sru        t.runTests();
5180728Sbrian    }
5280728Sbrian
5353537Sbrian    @Test
5480728Sbrian    public void testSimple(Path base) throws Exception {
5580728Sbrian        Path legacySrc = base.resolve("legacy-src");
5677760Ssobomax        tb.writeJavaFiles(legacySrc,
5753537Sbrian                          "package api; import java.awt.event.ActionListener; public abstract class Api implements ActionListener {}");
5853537Sbrian        Path legacyClasses = base.resolve("legacy-classes");
5999500Scharnier        Files.createDirectories(legacyClasses);
6053537Sbrian
6199500Scharnier        String log = new JavacTask(tb)
6253537Sbrian                .options()
6353537Sbrian                .outdir(legacyClasses)
6453537Sbrian                .files(findJavaFiles(legacySrc))
6553537Sbrian                .run()
6686783Sru                .writeAll()
6753537Sbrian                .getOutput(Task.OutputKind.DIRECT);
6853537Sbrian
6953537Sbrian        if (!log.isEmpty()) {
7053537Sbrian            throw new Exception("unexpected output: " + log);
7180728Sbrian        }
7280728Sbrian
7353537Sbrian        Path modulePath = base.resolve("module-path");
7453537Sbrian
7553537Sbrian        Files.createDirectories(modulePath);
7653537Sbrian
7753537Sbrian        Path jar = modulePath.resolve("test-api-1.0.jar");
7886783Sru
7980728Sbrian        new JarTask(tb, jar)
8080728Sbrian          .baseDir(legacyClasses)
8181251Sru          .files("api/Api.class")
8281251Sru          .run();
8353537Sbrian
8453537Sbrian        Path moduleSrc = base.resolve("module-src");
8580728Sbrian        Path m1 = moduleSrc.resolve("m1");
8686783Sru
8786783Sru        Path classes = base.resolve("classes");
8886783Sru
8979754Sdd        Files.createDirectories(classes);
9053537Sbrian
9153537Sbrian        tb.writeJavaFiles(m1,
9286783Sru                          "module m1 { requires test.api; requires java.desktop; }",
9353537Sbrian                          "package impl; public class Impl { public void e(api.Api api) { api.actionPerformed(null); } }");
9480728Sbrian
9580728Sbrian        new JavacTask(tb)
9680728Sbrian                .options("--module-source-path", moduleSrc.toString(), "--module-path", modulePath.toString())
9780728Sbrian                .outdir(classes)
9880728Sbrian                .files(findJavaFiles(moduleSrc))
9980728Sbrian                .run()
10053537Sbrian                .writeAll();
10180728Sbrian    }
10280728Sbrian
10353537Sbrian    @Test
10480728Sbrian    public void testUnnamedModule(Path base) throws Exception {
10580728Sbrian        Path legacySrc = base.resolve("legacy-src");
10680728Sbrian        tb.writeJavaFiles(legacySrc,
10780728Sbrian                          "package api; public abstract class Api { public void run(CharSequence str) { } private void run(base.Base base) { } }",
10853537Sbrian                          "package base; public interface Base { public void run(); }");
10953537Sbrian        Path legacyClasses = base.resolve("legacy-classes");
11053537Sbrian        Files.createDirectories(legacyClasses);
11181251Sru
11281251Sru        String log = new JavacTask(tb)
11353537Sbrian                .options()
11453537Sbrian                .outdir(legacyClasses)
11590975Sbrian                .files(findJavaFiles(legacySrc))
11686783Sru                .run()
11790975Sbrian                .writeAll()
11890975Sbrian                .getOutput(Task.OutputKind.DIRECT);
11990975Sbrian
12090975Sbrian        if (!log.isEmpty()) {
12186756Sbrian            throw new Exception("unexpected output: " + log);
12253537Sbrian        }
12353537Sbrian
12453537Sbrian        Path modulePath = base.resolve("module-path");
12553537Sbrian
12653537Sbrian        Files.createDirectories(modulePath);
12753537Sbrian
12853537Sbrian        Path apiJar = modulePath.resolve("test-api-1.0.jar");
12986783Sru
13053537Sbrian        new JarTask(tb, apiJar)
13153537Sbrian          .baseDir(legacyClasses)
13253537Sbrian          .files("api/Api.class")
13353537Sbrian          .run();
13480728Sbrian
13580728Sbrian        Path baseJar = base.resolve("base.jar");
13653537Sbrian
13786783Sru        new JarTask(tb, baseJar)
13853537Sbrian          .baseDir(legacyClasses)
13953537Sbrian          .files("base/Base.class")
14080728Sbrian          .run();
14180728Sbrian
14253537Sbrian        Path moduleSrc = base.resolve("module-src");
14386783Sru        Path m1 = moduleSrc.resolve("m1");
14453537Sbrian
14553537Sbrian        Path classes = base.resolve("classes");
14653537Sbrian
14753537Sbrian        Files.createDirectories(classes);
14853537Sbrian
14986783Sru        tb.writeJavaFiles(m1,
15053537Sbrian                          "module m1 { requires test.api; }",
15153537Sbrian                          "package impl; public class Impl { public void e(api.Api api) { api.run(\"\"); } }");
15266602Sbrian
15366602Sbrian        new JavacTask(tb)
15486783Sru                .options("--module-source-path", moduleSrc.toString(), "--module-path", modulePath.toString(), "--class-path", baseJar.toString())
15566602Sbrian                .outdir(classes)
15666602Sbrian                .files(findJavaFiles(moduleSrc))
15766602Sbrian                .run()
15853609Sbrian                .writeAll();
15953609Sbrian    }
16053609Sbrian
16153609Sbrian    @Test
16253609Sbrian    public void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception {
16353609Sbrian        Path automaticSrc = base.resolve("automaticSrc");
16453537Sbrian        tb.writeJavaFiles(automaticSrc, "package api; public class Api {}");
16553537Sbrian        Path automaticClasses = base.resolve("automaticClasses");
16653537Sbrian        tb.createDirectories(automaticClasses);
16753537Sbrian
16853537Sbrian        String automaticLog = new JavacTask(tb)
16953537Sbrian                                .outdir(automaticClasses)
17053537Sbrian                                .files(findJavaFiles(automaticSrc))
17180728Sbrian                                .run()
17280728Sbrian                                .writeAll()
17353537Sbrian                                .getOutput(Task.OutputKind.DIRECT);
17486783Sru
17553537Sbrian        if (!automaticLog.isEmpty())
176141851Sru            throw new Exception("expected output not found: " + automaticLog);
17753537Sbrian
17886783Sru        Path modulePath = base.resolve("module-path");
17953537Sbrian
18066602Sbrian        Files.createDirectories(modulePath);
18166602Sbrian
18266602Sbrian        Path automaticJar = modulePath.resolve("automatic-1.0.jar");
18366602Sbrian
18453537Sbrian        new JarTask(tb, automaticJar)
18553537Sbrian          .baseDir(automaticClasses)
18653537Sbrian          .files("api/Api.class")
18786783Sru          .run();
18886783Sru
18986783Sru        Path depSrc = base.resolve("depSrc");
19086783Sru        Path depClasses = base.resolve("depClasses");
19153537Sbrian
19253537Sbrian        Files.createDirectories(depSrc);
19353537Sbrian        Files.createDirectories(depClasses);
19453537Sbrian
19586783Sru        tb.writeJavaFiles(depSrc,
19653537Sbrian                          "module m1 { requires transitive automatic; }",
19766602Sbrian                          "package dep; public class Dep { api.Api api; }");
19853537Sbrian
19977760Ssobomax        new JavacTask(tb)
20077760Ssobomax                .options("--module-path", modulePath.toString())
20177760Ssobomax                .outdir(depClasses)
20279211Sru                .files(findJavaFiles(depSrc))
20353537Sbrian                .run()
20453537Sbrian                .writeAll();
205140414Sru
206140414Sru        Path moduleJar = modulePath.resolve("m1.jar");
207140414Sru
208140414Sru        new JarTask(tb, moduleJar)
209140414Sru          .baseDir(depClasses)
210140414Sru          .files("module-info.class", "dep/Dep.class")
211140414Sru          .run();
21253537Sbrian
21353537Sbrian        Path testSrc = base.resolve("testSrc");
21453537Sbrian        Path testClasses = base.resolve("testClasses");
21580728Sbrian
21680728Sbrian        Files.createDirectories(testSrc);
21753537Sbrian        Files.createDirectories(testClasses);
21880728Sbrian
21980728Sbrian        tb.writeJavaFiles(testSrc,
220                          "module m2 { requires automatic; }",
221                          "package test; public class Test { }");
222
223        new JavacTask(tb)
224                .options("--module-path", modulePath.toString())
225                .outdir(testClasses)
226                .files(findJavaFiles(testSrc))
227                .run()
228                .writeAll();
229    }
230
231    @Test
232    public void testAutomaticAndNamedModules(Path base) throws Exception {
233        Path modulePath = base.resolve("module-path");
234
235        Files.createDirectories(modulePath);
236
237        for (char c : new char[] {'A', 'B'}) {
238            Path automaticSrc = base.resolve("automaticSrc" + c);
239            tb.writeJavaFiles(automaticSrc, "package api" + c + "; public class Api {}");
240            Path automaticClasses = base.resolve("automaticClasses" + c);
241            tb.createDirectories(automaticClasses);
242
243            String automaticLog = new JavacTask(tb)
244                                    .outdir(automaticClasses)
245                                    .files(findJavaFiles(automaticSrc))
246                                    .run()
247                                    .writeAll()
248                                    .getOutput(Task.OutputKind.DIRECT);
249
250            if (!automaticLog.isEmpty())
251                throw new Exception("expected output not found: " + automaticLog);
252
253            Path automaticJar = modulePath.resolve("automatic" + c + "-1.0.jar");
254
255            new JarTask(tb, automaticJar)
256              .baseDir(automaticClasses)
257              .files("api" + c + "/Api.class")
258              .run();
259        }
260
261        Path moduleSrc = base.resolve("module-src");
262
263        tb.writeJavaFiles(moduleSrc.resolve("m1"),
264                          "module m1 { requires static automaticA; }",
265                          "package impl; public class Impl { apiA.Api a; apiB.Api b; m2.M2 m;}");
266
267        tb.writeJavaFiles(moduleSrc.resolve("m2"),
268                          "module m2 { exports m2; }",
269                          "package m2; public class M2 { }");
270
271        Path classes = base.resolve("classes");
272
273        Files.createDirectories(classes);
274
275        List<String> log = new JavacTask(tb)
276                .options("--module-source-path", moduleSrc.toString(),
277                         "--module-path", modulePath.toString(),
278                         "--add-modules", "automaticB",
279                         "-XDrawDiagnostics")
280                .outdir(classes)
281                .files(findJavaFiles(moduleSrc))
282                .run(Task.Expect.FAIL)
283                .writeAll()
284                .getOutputLines(Task.OutputKind.DIRECT);
285
286        List<String> expected = Arrays.asList("Impl.java:1:61: compiler.err.not.def.access.package.cant.access: m2.M2, m2",
287                                              "1 error");
288
289        if (!expected.equals(log)) {
290            throw new Exception("expected output not found: " + log);
291        }
292
293        log = new JavacTask(tb)
294                .options("--module-source-path", moduleSrc.toString(),
295                         "--module-path", modulePath.toString(),
296                         "-XDrawDiagnostics")
297                .outdir(classes)
298                .files(findJavaFiles(moduleSrc))
299                .run(Task.Expect.FAIL)
300                .writeAll()
301                .getOutputLines(Task.OutputKind.DIRECT);
302
303        expected = Arrays.asList("Impl.java:1:51: compiler.err.doesnt.exist: apiB",
304                                 "Impl.java:1:61: compiler.err.not.def.access.package.cant.access: m2.M2, m2",
305                                 "2 errors");
306
307        if (!expected.equals(log)) {
308            throw new Exception("expected output not found: " + log);
309        }
310    }
311
312    @Test
313    public void testDropTrailingVersion(Path base) throws Exception {
314        Path legacySrc = base.resolve("legacy-src");
315        tb.writeJavaFiles(legacySrc,
316                          "package api; public class Api {}");
317        Path legacyClasses = base.resolve("legacy-classes");
318        Files.createDirectories(legacyClasses);
319
320        String log = new JavacTask(tb)
321                .options()
322                .outdir(legacyClasses)
323                .files(findJavaFiles(legacySrc))
324                .run()
325                .writeAll()
326                .getOutput(Task.OutputKind.DIRECT);
327
328        if (!log.isEmpty()) {
329            throw new Exception("unexpected output: " + log);
330        }
331
332        Path modulePath = base.resolve("module-path");
333
334        Files.createDirectories(modulePath);
335
336        Path jar = modulePath.resolve("test1.jar");
337
338        new JarTask(tb, jar)
339          .baseDir(legacyClasses)
340          .files("api/Api.class")
341          .run();
342
343        Path moduleSrc = base.resolve("module-src");
344        Path m = moduleSrc.resolve("m");
345
346        Path classes = base.resolve("classes");
347
348        Files.createDirectories(classes);
349
350        tb.writeJavaFiles(m,
351                          "module m { requires test; }",
352                          "package impl; public class Impl { public void e(api.Api api) { } }");
353
354        new JavacTask(tb)
355                .options("--module-source-path", moduleSrc.toString(), "--module-path", modulePath.toString())
356                .outdir(classes)
357                .files(findJavaFiles(moduleSrc))
358                .run()
359                .writeAll();
360    }
361}
362