1 /* 2 * Copyright (c) 2018, 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 * @bug 8198315 27 * @summary Verify that diagnostics can be printed without throwing CompletionFailures 28 * @library /tools/lib 29 * @modules jdk.compiler/com.sun.tools.javac.api 30 * jdk.compiler/com.sun.tools.javac.main 31 * @build toolbox.TestRunner toolbox.ToolBox CompletionFailureInDiags 32 * @run main CompletionFailureInDiags 33 */ 34 35 import java.nio.file.Files; 36 import java.nio.file.Path; 37 import java.nio.file.Paths; 38 import java.util.List; 39 import java.util.Objects; 40 41 import toolbox.JavacTask; 42 import toolbox.Task.Expect; 43 import toolbox.Task.OutputKind; 44 import toolbox.TestRunner; 45 import toolbox.TestRunner.Test; 46 import toolbox.ToolBox; 47 48 public class CompletionFailureInDiags extends TestRunner { 49 main(String... args)50 public static void main(String... args) throws Exception { 51 new CompletionFailureInDiags().runTests(m -> new Object[] { Paths.get(m.getName()) }); 52 } 53 54 private final ToolBox tb = new ToolBox(); 55 CompletionFailureInDiags()56 public CompletionFailureInDiags() { 57 super(System.err); 58 } 59 60 @Test testCrashInDiagReport(Path outerBase)61 public void testCrashInDiagReport(Path outerBase) throws Exception { 62 int c = 0; 63 64 for (Bound bound : Bound.values()) { 65 for (AdditionalParams params : AdditionalParams.values()) { 66 for (Delete delete : Delete.values()) { 67 doRunCrashTest(outerBase.resolve(String.valueOf(c++)), bound, params, delete); 68 } 69 } 70 } 71 } 72 73 private enum Bound { 74 A("A"), 75 AA2("A&A2"); 76 private final String bound; 77 Bound(String bound)78 private Bound(String bound) { 79 this.bound = bound; 80 } 81 82 } 83 84 private enum AdditionalParams { 85 NONE(new String[0], null), 86 RAD_DIAGS(new String[] {"-XDrawDiagnostics"}, 87 List.of("Test.java:3:10: compiler.err.cant.apply.symbol: kindname.method, " + 88 "f, " + 89 "java.lang.String, " + 90 "compiler.misc.type.null,compiler.misc.type.null, " + 91 "kindname.class, " + 92 "D<T>, " + 93 "(compiler.misc.arg.length.mismatch)", 94 "1 error")); 95 private final String[] options; 96 private final List<String> expected; 97 AdditionalParams(String[] options, List<String> expected)98 private AdditionalParams(String[] options, List<String> expected) { 99 this.options = options; 100 this.expected = expected; 101 } 102 103 } 104 105 private enum Delete { 106 NONE(), 107 A("A.class"), 108 AA2("A.class", "A2.class"); 109 private final String[] toDelete; 110 Delete(String... toDelete)111 private Delete(String... toDelete) { 112 this.toDelete = toDelete; 113 } 114 115 } 116 doRunCrashTest(Path outerBase, Bound bound, AdditionalParams params, Delete delete)117 private void doRunCrashTest(Path outerBase, Bound bound, AdditionalParams params, Delete delete) throws Exception { 118 Path libSrc = outerBase.resolve("lib-src"); 119 tb.writeJavaFiles(libSrc, 120 "public class A {}", 121 "public interface A2 {}", 122 "public class B extends A implements A2 {}", 123 "public class C extends D<B> {}\n", 124 "public class D<T extends " + bound.bound + "> {\n" + 125 " public void f(String s) {}\n" + 126 "}"); 127 Path lib = outerBase.resolve("lib"); 128 Files.createDirectories(lib); 129 new JavacTask(tb) 130 .outdir(lib.toString()) 131 .files(tb.findJavaFiles(libSrc)) 132 .run() 133 .writeAll(); 134 for (String del : delete.toDelete) { 135 Files.delete(lib.resolve(del)); 136 } 137 Path src = outerBase.resolve("src"); 138 tb.writeJavaFiles(src, 139 "public class Test {\n" + 140 " public void test(C c) {\n" + 141 " c.f(null, null);\n" + 142 " }\n" + 143 "}"); 144 Path classes = outerBase.resolve("classes"); 145 Files.createDirectories(classes); 146 List<String> actual = new JavacTask(tb) 147 .options(params.options) 148 .classpath(lib) 149 .outdir(classes.toString()) 150 .sourcepath() 151 .files(tb.findJavaFiles(src)) 152 .run(Expect.FAIL) 153 .writeAll() 154 .getOutputLines(OutputKind.DIRECT); 155 156 if (params.expected != null && !Objects.equals(params.expected, actual)) { 157 throw new AssertionError("Unexpected output!"); 158 } 159 } 160 161 } 162