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