--- old/test/tools/javac/modules/XModuleTest.java 2017-02-08 11:44:48.581943383 -0800 +++ new/test/tools/javac/modules/XModuleTest.java 2017-02-08 11:44:48.443942346 -0800 @@ -40,6 +40,7 @@ import java.util.Arrays; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; @@ -167,8 +168,7 @@ tb.createDirectories(classes); List log = new JavacTask(tb) - .options("--patch-module", "m1x=" + m1.toString(), - "--patch-module", "m2x=" + m2.toString(), + .options("--patch-module", "m1x=" + m2.toString(), "--module-source-path", src.toString(), "-XDrawDiagnostics") .outdir(classes) @@ -179,11 +179,8 @@ .getOutputLines(Task.OutputKind.DIRECT); List expectedOut = Arrays.asList( - "Test.java:1:1: compiler.err.file.patched.and.msp", - "Test.java:1:1: compiler.err.file.patched.and.msp", - "module-info.java:1:1: compiler.err.file.patched.and.msp", - "- compiler.err.cant.access: m2x.module-info, (compiler.misc.cant.resolve.modules)", - "4 errors" + "Test.java:1:1: compiler.err.file.patched.and.msp: m1x, m2x", + "1 error" ); if (!expectedOut.equals(log)) @@ -266,14 +263,15 @@ //note: avoiding use of java.base, as that gets special handling on some places: Path src = base.resolve("src"); tb.writeJavaFiles(src, + "module java.compiler {}", "package javax.lang.model.element; public interface Extra { }"); - Path srcPath = base.resolve("src-path"); - tb.writeJavaFiles(src, - "module java.compiler {}"); Path classes = base.resolve("classes"); tb.createDirectories(classes); - List log = new JavacTask(tb) + List log; + List expected; + + log = new JavacTask(tb) .options("-XDrawDiagnostics", "--patch-module", "java.compiler=" + src.toString()) .outdir(classes) @@ -282,8 +280,25 @@ .writeAll() .getOutputLines(Task.OutputKind.DIRECT); - List expected = Arrays.asList("Extra.java:1:1: compiler.err.module-info.with.patched.module.sourcepath", - "1 error"); + expected = Arrays.asList("Extra.java:1:1: compiler.err.module-info.with.patched.module.sourcepath", + "1 error"); + + if (!expected.equals(log)) + throw new Exception("expected output not found: " + log); + + //multi-module mode: + log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--patch-module", "java.compiler=" + src.toString(), + "--module-source-path", "dummy") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expected = Arrays.asList("- compiler.err.locn.module-info.not.allowed.on.patch.path: module-info.java", + "1 error"); if (!expected.equals(log)) throw new Exception("expected output not found: " + log); @@ -295,7 +310,7 @@ Path srcMod = base.resolve("src-mod"); tb.writeJavaFiles(srcMod, "module mod {}"); - Path classes = base.resolve("classes"); + Path classes = base.resolve("classes").resolve("java.compiler"); tb.createDirectories(classes); String logMod = new JavacTask(tb) @@ -314,7 +329,10 @@ "package javax.lang.model.element; public interface Extra { }"); tb.createDirectories(classes); - List log = new JavacTask(tb) + List log; + List expected; + + log = new JavacTask(tb) .options("-XDrawDiagnostics", "--patch-module", "java.compiler=" + src.toString()) .outdir(classes) @@ -323,8 +341,24 @@ .writeAll() .getOutputLines(Task.OutputKind.DIRECT); - List expected = Arrays.asList("Extra.java:1:1: compiler.err.module-info.with.patched.module.classpath", - "1 error"); + expected = Arrays.asList("Extra.java:1:1: compiler.err.module-info.with.patched.module.classoutput", + "1 error"); + + if (!expected.equals(log)) + throw new Exception("expected output not found: " + log); + + log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "--patch-module", "java.compiler=" + src.toString(), + "--module-source-path", "dummy") + .outdir(classes.getParent()) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + expected = Arrays.asList("- compiler.err.locn.module-info.not.allowed.on.patch.path: module-info.class", + "1 error"); if (!expected.equals(log)) throw new Exception("expected output not found: " + log); @@ -496,6 +530,160 @@ } } + @Test + public void testSingleModeIncremental(Path base) throws Exception { + //note: avoiding use of java.base, as that gets special handling on some places: + Path src = base.resolve("src"); + tb.writeJavaFiles(src, + "package javax.lang.model.element; public interface Extra extends Element { }", + "package javax.lang.model.element; public interface Extra2 extends Extra { }"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + Thread.sleep(2000); //ensure newer timestamps on classfiles: + + new JavacTask(tb) + .options("--patch-module", "java.compiler=" + src.toString()) + .outdir(classes) + .files(findJavaFiles(src)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + List log = new JavacTask(tb) + .options("--patch-module", "java.compiler=" + src.toString(), + "-verbose") + .outdir(classes) + .files(findJavaFiles(src.resolve("javax/lang/model/element/Extra2.java" + .replace("/", src.getFileSystem().getSeparator())))) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT) + .stream() + .filter(l -> l.contains("parsing")) + .collect(Collectors.toList()); + + boolean parsesExtra2 = log.stream() + .anyMatch(l -> l.contains("Extra2.java")); + boolean parsesExtra = log.stream() + .anyMatch(l -> l.contains("Extra.java")); + + if (!parsesExtra2 || parsesExtra) { + throw new AssertionError("Unexpected output: " + log); + } + } + + @Test + public void testComplexMSPAndPatch(Path base) throws Exception { + //note: avoiding use of java.base, as that gets special handling on some places: + Path src1 = base.resolve("src1"); + Path src1ma = src1.resolve("ma"); + tb.writeJavaFiles(src1ma, + "module ma { exports ma; }", + "package ma; public class C1 { public static void method() { } }", + "package ma.impl; public class C2 { }"); + Path src1mb = src1.resolve("mb"); + tb.writeJavaFiles(src1mb, + "module mb { requires ma; }", + "package mb.impl; public class C2 { public static void method() { } }"); + Path src1mc = src1.resolve("mc"); + tb.writeJavaFiles(src1mc, + "module mc { }"); + Path classes1 = base.resolve("classes1"); + tb.createDirectories(classes1); + tb.cleanDirectory(classes1); + + new JavacTask(tb) + .options("--module-source-path", src1.toString()) + .files(findJavaFiles(src1)) + .outdir(classes1) + .run() + .writeAll(); + + //patching: + Path src2 = base.resolve("src2"); + Path src2ma = src2.resolve("ma"); + tb.writeJavaFiles(src2ma, + "package ma.impl; public class C2 { public static void extra() { ma.C1.method(); } }", + "package ma.impl; public class C3 { public void test() { C2.extra(); } }"); + Path src2mb = src2.resolve("mb"); + tb.writeJavaFiles(src2mb, + "package mb.impl; public class C3 { public void test() { C2.method(); ma.C1.method(); ma.impl.C2.extra(); } }"); + Path src2mc = src2.resolve("mc"); + tb.writeJavaFiles(src2mc, + "package mc.impl; public class C2 { public static void test() { } }", + //will require --add-reads ma: + "package mc.impl; public class C3 { public static void test() { ma.impl.C2.extra(); } }"); + Path src2mt = src2.resolve("mt"); + tb.writeJavaFiles(src2mt, + "module mt { requires ma; requires mb; }", + "package mt.impl; public class C2 { public static void test() { mb.impl.C2.method(); ma.impl.C2.extra(); } }", + "package mt.impl; public class C3 { public static void test() { C2.test(); mc.impl.C2.test(); } }"); + Path classes2 = base.resolve("classes2"); + tb.createDirectories(classes2); + tb.cleanDirectory(classes2); + + Thread.sleep(2000); //ensure newer timestamps on classfiles: + + new JavacTask(tb) + .options("--module-path", classes1.toString(), + "--patch-module", "ma=" + src2ma.toString(), + "--patch-module", "mb=" + src2mb.toString(), + "--add-exports", "ma/ma.impl=mb", + "--patch-module", "mc=" + src2mc.toString(), + "--add-reads", "mc=ma", + "--add-exports", "ma/ma.impl=mc", + "--add-exports", "ma/ma.impl=mt", + "--add-exports", "mb/mb.impl=mt", + "--add-exports", "mc/mc.impl=mt", + "--add-reads", "mt=mc", + "--module-source-path", src2.toString()) + .outdir(classes2) + .files(findJavaFiles(src2)) + .run() + .writeAll(); + + //incremental compilation (C2 mustn't be compiled, C3 must): + tb.writeJavaFiles(src2ma, + "package ma.impl; public class C3 { public void test() { ma.C1.method(); C2.extra(); } }"); + tb.writeJavaFiles(src2mt, + "package mt.impl; public class C3 { public static void test() { mc.impl.C2.test(); C2.test(); } }"); + + List log = new JavacTask(tb) + .options("--module-path", classes1.toString(), + "--patch-module", "ma=" + src2ma.toString(), + "--patch-module", "mb=" + src2mb.toString(), + "--add-exports", "ma/ma.impl=mb", + "--patch-module", "mc=" + src2mc.toString(), + "--add-reads", "mc=ma", + "--add-exports", "ma/ma.impl=mc", + "--add-exports", "ma/ma.impl=mt", + "--add-exports", "mb/mb.impl=mt", + "--add-exports", "mc/mc.impl=mt", + "--add-reads", "mt=mc", + "--module-source-path", src2.toString(), + "--add-modules", "mc", + "-verbose") + .outdir(classes2) + .files(src2ma.resolve("ma").resolve("impl").resolve("C3.java"), + src2mt.resolve("mt").resolve("impl").resolve("C3.java")) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT) + .stream() + .filter(l -> l.contains("parsing")) + .collect(Collectors.toList()); + + boolean parsesC3 = log.stream() + .anyMatch(l -> l.contains("C3.java")); + boolean parsesC2 = log.stream() + .anyMatch(l -> l.contains("C2.java")); + + if (!parsesC3 || parsesC2) { + throw new AssertionError("Unexpected output: " + log); + } + } + private void checkFileExists(Path dir, String path) { Path toCheck = dir.resolve(path.replace("/", dir.getFileSystem().getSeparator()));