| /* |
| * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * @test |
| * @summary tests for --module-source-path |
| * @library /tools/lib |
| * @modules |
| * jdk.compiler/com.sun.tools.javac.api |
| * jdk.compiler/com.sun.tools.javac.main |
| * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase |
| * @run main ModuleSourcePathTest |
| */ |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.stream.Collectors; |
| import java.util.stream.Stream; |
| |
| import javax.tools.JavaCompiler; |
| import javax.tools.JavaFileManager.Location; |
| import javax.tools.StandardJavaFileManager; |
| import javax.tools.StandardLocation; |
| import javax.tools.ToolProvider; |
| |
| import toolbox.JavacTask; |
| import toolbox.Task; |
| import toolbox.ToolBox; |
| |
| public class ModuleSourcePathTest extends ModuleTestBase { |
| |
| public static final char PATH_SEP = File.pathSeparatorChar; |
| |
| public static void main(String... args) throws Exception { |
| ModuleSourcePathTest t = new ModuleSourcePathTest(); |
| t.runTests(); |
| } |
| |
| @Test |
| public void testSourcePathConflict(Path base) throws Exception { |
| Path sp = base.resolve("src"); |
| Path msp = base.resolve("srcmodules"); |
| |
| String log = new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--source-path", sp.toString().replace('/', File.separatorChar), |
| "--module-source-path", msp.toString().replace('/', File.separatorChar), |
| "dummyClass") |
| .run(Task.Expect.FAIL) |
| .writeAll() |
| .getOutput(Task.OutputKind.DIRECT); |
| |
| if (!log.contains("cannot specify both --source-path and --module-source-path")) |
| throw new Exception("expected diagnostic not found"); |
| } |
| |
| @Test |
| public void testUnnormalizedPath1(Path base) throws Exception { |
| Path src = base.resolve("src"); |
| Path src_m1 = src.resolve("m1x"); |
| tb.writeJavaFiles(src_m1, "module m1x { }"); |
| Path modules = base.resolve("modules"); |
| Files.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", src.toString()) |
| .outdir(modules) |
| .files(prefixAll(findJavaFiles(src), Paths.get("./"))) |
| .run() |
| .writeAll(); |
| } |
| |
| @Test |
| public void testUnnormalizedPath2(Path base) throws Exception { |
| Path src = base.resolve("src"); |
| Path src_m1 = src.resolve("m1x"); |
| tb.writeJavaFiles(src_m1, "module m1x { }"); |
| Path modules = base.resolve("modules"); |
| Files.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", "./" + src) |
| .outdir(modules) |
| .files(findJavaFiles(src)) |
| .run() |
| .writeAll(); |
| } |
| |
| private Path[] prefixAll(Path[] paths, Path prefix) { |
| return Stream.of(paths) |
| .map(prefix::resolve) |
| .collect(Collectors.toList()) |
| .toArray(new Path[paths.length]); |
| } |
| |
| @Test |
| public void regularBraces(Path base) throws Exception { |
| generateModules(base, "src1", "src2/inner_dir"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "/{src1,src2/inner_dir}") |
| .files(base.resolve("src1/m0x/pkg0/A.java"), base.resolve("src2/inner_dir/m1x/pkg1/A.java")) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("m0x/pkg0/A.class"), |
| modules.resolve("m1x/pkg1/A.class"), |
| modules.resolve("m0x/module-info.class"), |
| modules.resolve("m1x/module-info.class")); |
| } |
| |
| @Test |
| public void mismatchedBraces(Path base) throws Exception { |
| final List<String> sourcePaths = Arrays.asList( |
| "{", |
| "}", |
| "}{", |
| "./}", |
| ".././{./", |
| "src{}}", |
| "{{}{}}{}}", |
| "src/{a,b}/{", |
| "src/{a,{,{}}", |
| "{.,..{}/src", |
| "*}{", |
| "{}*}" |
| ); |
| for (String sourcepath : sourcePaths) { |
| String log = new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", sourcepath.replace('/', File.separatorChar)) |
| .run(Task.Expect.FAIL) |
| .writeAll() |
| .getOutput(Task.OutputKind.DIRECT); |
| |
| if (!log.contains("- compiler.err.illegal.argument.for.option: --module-source-path, mismatched braces")) |
| throw new Exception("expected output for path [" + sourcepath + "] not found"); |
| } |
| } |
| |
| @Test |
| public void deepBraces(Path base) throws Exception { |
| String[] modulePaths = {"src/src1", |
| "src/src2", |
| "src/src3", |
| "src/srcB/src1", |
| "src/srcB/src2/srcXX", |
| "src/srcB/src2/srcXY", |
| "src/srcC/src1", |
| "src/srcC/src2/srcXX", |
| "src/srcC/src2/srcXY"}; |
| generateModules(base, modulePaths); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", |
| base + "/{src/{{src1,src2,src3},{srcB,srcC}/{src1,src2/srcX{X,Y}/}},.}" |
| .replace('/', File.separatorChar)) |
| .files(findJavaFiles(base.resolve(modulePaths[modulePaths.length - 1]))) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| for (int i = 0; i < modulePaths.length; i++) { |
| checkFiles(modules.resolve("m" + i + "x/module-info.class")); |
| } |
| checkFiles(modules.resolve("m8x/pkg8/A.class")); |
| } |
| |
| @Test |
| public void fileInPath(Path base) throws Exception { |
| Path src = base.resolve("src"); |
| tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }"); |
| tb.writeFile(base.resolve("dummy.txt"), ""); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "/{dummy.txt,src}") |
| .files(src.resolve("kettle$/electric/Heater.java")) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("kettle$/electric/Heater.class")); |
| checkFiles(modules.resolve("kettle$/module-info.class")); |
| } |
| |
| @Test |
| public void noAlternative(Path base) throws Exception { |
| Path src = base.resolve("src"); |
| tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "/{src}") |
| .files(src.resolve("kettle$/electric/Heater.java")) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("kettle$/electric/Heater.class")); |
| checkFiles(modules.resolve("kettle$/module-info.class")); |
| } |
| |
| @Test |
| public void noChoice(Path base) throws Exception { |
| tb.writeJavaFiles(base.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "/{}") |
| .files(base.resolve("kettle$/electric/Heater.java")) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("kettle$/electric/Heater.class")); |
| checkFiles(modules.resolve("kettle$/module-info.class")); |
| } |
| |
| @Test |
| public void nestedModules(Path src) throws Exception { |
| Path carModule = src.resolve("car"); |
| tb.writeJavaFiles(carModule, "module car { }", "package light; class Headlight { }"); |
| tb.writeJavaFiles(carModule.resolve("engine"), "module engine { }", "package flat; class Piston { }"); |
| |
| final Path modules = src.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", "{" + src + "," + src + "/car}") |
| .files(findJavaFiles(src)) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| checkFiles(modules.resolve("car/light/Headlight.class")); |
| checkFiles(modules.resolve("engine/flat/Piston.class")); |
| } |
| |
| @Test |
| public void relativePaths(Path base) throws Exception { |
| Path src = base.resolve("src"); |
| tb.writeJavaFiles(src.resolve("kettle"), "module kettle { }", "package electric; class Heater { }"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "/src/./../src") |
| .files(src.resolve("kettle/electric/Heater.java")) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| checkFiles(modules.resolve("kettle/electric/Heater.class")); |
| checkFiles(modules.resolve("kettle/module-info.class")); |
| } |
| |
| @Test |
| public void duplicatePaths(Path base) throws Exception { |
| Path src = base.resolve("src"); |
| tb.writeJavaFiles(src.resolve("m1x"), "module m1x { }", "package a; class A { }"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "/{src,src,src}") |
| .files(src.resolve("m1x/a/A.java")) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("m1x/module-info.class")); |
| } |
| |
| @Test |
| public void notExistentPaths(Path base) throws Exception { |
| tb.writeJavaFiles(base.resolve("m1x"), "module m1x { requires m0x; }", "package a; class A { }"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| String log = new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "/not_exist" + PATH_SEP + base + "/{not_exist,}") |
| .files(base.resolve("m1x/a/A.java")) |
| .outdir(modules) |
| .run(Task.Expect.FAIL) |
| .writeAll() |
| .getOutput(Task.OutputKind.DIRECT); |
| if (!log.contains("compiler.err.module.not.found: m0x")) |
| throw new Exception("expected output for not existent module source path not found"); |
| } |
| |
| @Test |
| public void notExistentPathShouldBeSkipped(Path base) throws Exception { |
| tb.writeJavaFiles(base.resolve("m1x"), "module m1x { }", "package a; class A { }"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "{/not_exist,/}") |
| .files(base.resolve("m1x/a/A.java")) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("m1x/module-info.class")); |
| } |
| |
| @Test |
| public void commas(Path base) throws Exception { |
| Path src = base.resolve("src"); |
| tb.writeJavaFiles(src.resolve("m1x"), "module m1x { }", "package a; class A { }"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "/{,{,,,,src,,,}}") |
| .files(src.resolve("m1x/a/A.java")) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("m1x/module-info.class")); |
| } |
| |
| @Test |
| public void asterisk(Path base) throws Exception { |
| tb.writeJavaFiles(base.resolve("kettle").resolve("classes"), "module kettle { }", |
| "package electric; class Heater { }"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", base + "/*/classes/") |
| .files(base.resolve("kettle/classes/electric/Heater.java")) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("kettle/electric/Heater.class")); |
| checkFiles(modules.resolve("kettle/module-info.class")); |
| } |
| |
| @Test |
| public void asteriskInDifferentSets(Path base) throws Exception { |
| Path src = base.resolve("src"); |
| final Path module = src.resolve("kettle"); |
| tb.writeJavaFiles(module.resolve("classes"), "module kettle { }", "package electric; class Heater { }"); |
| tb.writeJavaFiles(module.resolve("gensrc"), "package model; class Java { }"); |
| tb.writeJavaFiles(module.resolve("special/classes"), "package gas; class Heater { }"); |
| |
| final Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", src + "{/*/gensrc/,/*/classes/}" + PATH_SEP |
| + src + "/*/special/classes") |
| .files(findJavaFiles(src)) |
| .outdir(modules) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("kettle/electric/Heater.class")); |
| checkFiles(modules.resolve("kettle/gas/Heater.class")); |
| checkFiles(modules.resolve("kettle/model/Java.class")); |
| checkFiles(modules.resolve("kettle/module-info.class")); |
| } |
| |
| @Test |
| public void asteriskIllegalUse(Path base) throws Exception { |
| final List<String> sourcePaths = Arrays.asList( |
| "*", |
| "**", |
| "***", |
| "*.*", |
| ".*", |
| "*.", |
| "src/*/*/", |
| "{*,*}", |
| "src/module*/" |
| ); |
| for (String sourcepath : sourcePaths) { |
| String log = new JavacTask(tb, Task.Mode.CMDLINE) |
| .options("-XDrawDiagnostics", |
| "--module-source-path", sourcepath.replace('/', File.separatorChar)) |
| .run(Task.Expect.FAIL) |
| .writeAll() |
| .getOutput(Task.OutputKind.DIRECT); |
| |
| if (!log.contains("- compiler.err.illegal.argument.for.option: --module-source-path, illegal use of *")) |
| throw new Exception("expected output for path [" + sourcepath + "] not found"); |
| } |
| } |
| |
| @Test |
| public void setLocation(Path base) throws Exception { |
| Path src = base.resolve("src"); |
| tb.writeJavaFiles(src.resolve("m1x"), "module m1x { }", "package a; class A { }"); |
| Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| JavaCompiler c = ToolProvider.getSystemJavaCompiler(); |
| try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) { |
| fm.setLocationFromPaths(StandardLocation.MODULE_SOURCE_PATH, List.of(src)); |
| new JavacTask(tb) |
| .options("-XDrawDiagnostics") |
| .fileManager(fm) |
| .outdir(modules) |
| .files(findJavaFiles(src)) |
| .run() |
| .writeAll(); |
| |
| checkFiles(modules.resolve("m1x/module-info.class"), modules.resolve("m1x/a/A.class")); |
| } |
| } |
| |
| @Test |
| public void getLocation_valid(Path base) throws Exception { |
| Path src1 = base.resolve("src1"); |
| tb.writeJavaFiles(src1.resolve("m1x"), "module m1x { }", "package a; class A { }"); |
| Path src2 = base.resolve("src2"); |
| tb.writeJavaFiles(src1.resolve("m2x"), "module m2x { }", "package b; class B { }"); |
| |
| JavaCompiler c = ToolProvider.getSystemJavaCompiler(); |
| try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) { |
| fm.setLocationFromPaths(StandardLocation.MODULE_SOURCE_PATH, List.of(src1, src2)); |
| checkLocation(fm.getLocationAsPaths(StandardLocation.MODULE_SOURCE_PATH), List.of(src1, src2)); |
| } |
| } |
| |
| @Test |
| public void getLocation_ISA(Path base) throws Exception { |
| Path src1 = base.resolve("src1"); |
| tb.writeJavaFiles(src1.resolve("m1x"), "module m1x { }", "package a; class A { }"); |
| Path src2 = base.resolve("src2"); |
| tb.writeJavaFiles(src2.resolve("m2x").resolve("extra"), "module m2x { }", "package b; class B { }"); |
| Path modules = base.resolve("modules"); |
| tb.createDirectories(modules); |
| |
| String FS = File.separator; |
| String PS = File.pathSeparator; |
| JavaCompiler c = ToolProvider.getSystemJavaCompiler(); |
| try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) { |
| fm.handleOption("--module-source-path", |
| List.of(src1 + PS + src2 + FS + "*" + FS + "extra").iterator()); |
| |
| try { |
| Iterable<? extends Path> paths = fm.getLocationAsPaths(StandardLocation.MODULE_SOURCE_PATH); |
| out.println("result: " + asList(paths)); |
| throw new Exception("expected IllegalStateException not thrown"); |
| } catch (IllegalStateException e) { |
| out.println("Exception thrown, as expected: " + e); |
| } |
| |
| // even if we can't do getLocation for the MODULE_SOURCE_PATH, we should be able |
| // to do getLocation for the modules, which will additionally confirm the option |
| // was effective as intended. |
| Location locn1 = fm.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH, "m1x"); |
| checkLocation(fm.getLocationAsPaths(locn1), List.of(src1.resolve("m1x"))); |
| Location locn2 = fm.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH, "m2x"); |
| checkLocation(fm.getLocationAsPaths(locn2), List.of(src2.resolve("m2x").resolve("extra"))); |
| } |
| } |
| |
| private void generateModules(Path base, String... paths) throws IOException { |
| for (int i = 0; i < paths.length; i++) { |
| String moduleName = "m" + i + "x"; |
| String dependency = i > 0 ? "requires m" + (i - 1) + "x;" : ""; |
| tb.writeJavaFiles(base.resolve(paths[i]).resolve(moduleName), |
| "module " + moduleName + " { " + dependency + " }", |
| "package pkg" + i + "; class A { }"); |
| } |
| } |
| |
| private void checkFiles(Path... files) throws Exception { |
| for (Path file : files) { |
| if (!Files.exists(file)) { |
| throw new Exception("File not found: " + file); |
| } |
| } |
| } |
| |
| private void checkLocation(Iterable<? extends Path> locn, List<Path> ref) throws Exception { |
| List<Path> list = asList(locn); |
| if (!list.equals(ref)) { |
| out.println("expect: " + ref); |
| out.println(" found: " + list); |
| throw new Exception("location not as expected"); |
| } |
| } |
| |
| private <T> List<T> asList(Iterable<? extends T> iter) { |
| List<T> list = new ArrayList<>(); |
| for (T item : iter) { |
| list.add(item); |
| } |
| return list; |
| } |
| } |