1 /*
2  * Copyright (c) 2019, 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 8223967
27  * @bug 8232681
28  * @summary Unit tests for Text Block language changes
29  * @library /tools/lib
30  * @modules jdk.compiler/com.sun.tools.javac.api
31  *          jdk.compiler/com.sun.tools.javac.main
32  * @build toolbox.ToolBox toolbox.JavacTask
33  * @run main TextBlockAPI
34  */
35 
36 import toolbox.JavacTask;
37 import toolbox.JavaTask;
38 import toolbox.Task;
39 import toolbox.ToolBox;
40 
41 public class TextBlockAPI {
42     private static ToolBox TOOLBOX = new ToolBox();
43     private final static String JDK_VERSION = Integer.toString(Runtime.version().feature());
44 
main(String... args)45     public static void main(String... args) {
46         test1();
47         test2();
48         test3();
49         test4();
50         test5();
51         test6();
52         test7();
53         test8();
54    }
55 
56     /*
57      * Check that correct/incorrect syntax is properly detected
58      */
test1()59     static void test1() {
60         for (String lineterminators : new String[] { "\n", "\r", "\r\n" })
61         for (String whitespace : new String[] { "", "   ", "\t", "\f" })
62         for (String content : new String[] { "a", "ab", "abc", "\u2022", "*".repeat(1000), "*".repeat(10000) })  {
63             String code =
64                     "public class CorrectTest {\n" +
65                             "    public static void main(String... args) {\n" +
66                             "        String xxx = " +
67                             "\"\"\"" + whitespace + lineterminators +
68                             content +
69                             "\"\"\";\n" +
70                             "    }\n" +
71                             "}\n";
72             compPass(code);
73         }
74     }
75 
76     /*
77      * Check that use of \u0022 is properly detected
78      */
test2()79     static void test2() {
80         compPass("public class UnicodeDelimiterTest {",
81                  "    public static void main(String... args) {",
82                  "        String xxx = \\u0022\\u0022\\u0022\nabc\n\\u0022\\u0022\\u0022;",
83                  "    }",
84                  "}");
85     }
86 
87     /*
88      * Check edge cases of text blocks as last token
89      */
test3()90     static void test3() {
91         compFail("public class EndTest {",
92                  "    public static void main(String... args) {",
93                  "        String xxx = \"\"\"\nabc\"\"\"");
94         compFail("public class TwoQuoteClose {",
95                  "    public static void main(String... args) {",
96                  "        String xxx = \"\"\"\nabc\"\"");
97         compFail("public class OneQuoteClose {",
98                  "    public static void main(String... args) {",
99                  "        String xxx = \"\"\"\nabc\"");
100         compFail("public class NoClose {",
101                  "    public static void main(String... args) {",
102                  "        String xxx = \"\"\"\nabc");
103         compFail("public class ZeroTerminator {",
104                  "    public static void main(String... args) {",
105                  "        String xxx = \"\"\"\nabc\\u0000");
106         compFail("public class NonBreakingSpace {",
107                  "    public static void main(String... args) {",
108                  "        String xxx = \"\"\"\nabc\\u001A");
109     }
110 
111     /*
112      * Check line terminator translation
113      */
test4()114     static void test4() {
115         String[] terminators = new String[] { "\n", "\r\n", "\r" };
116         for (String terminator : terminators) {
117             String code = "public class LineTerminatorTest {" + terminator +
118                           "    public static void main(String... args) {" + terminator +
119                           "        String s =" + terminator +
120                           "\"\"\"" + terminator +
121                           "abc" + terminator +
122                           "\"\"\";" + terminator +
123                           "        System.out.println(s.equals(\"abc\\n\"));" + terminator +
124                           "    }" + terminator +
125                           "}" + terminator;
126             new JavacTask(TOOLBOX)
127                     .sources(code)
128                     .classpath(".")
129                     .options("-encoding", "utf8")
130                     .run();
131             String output = new JavaTask(TOOLBOX)
132                     .classpath(".")
133                     .classArgs("LineTerminatorTest")
134                     .run()
135                     .writeAll()
136                     .getOutput(Task.OutputKind.STDOUT);
137 
138             if (!output.contains("true")) {
139                 throw new RuntimeException("Error detected");
140             }
141         }
142     }
143 
144     /*
145      * Check escape space
146      */
test5()147     static void test5() {
148         compPass("public class EscapeSChar {",
149                  "    public static void main(String... args) {",
150                  "        char xxx = '\\s';",
151                  "    }",
152                  "}");
153         compPass("public class EscapeSString {",
154                  "    public static void main(String... args) {",
155                  "        String xxx = \"\\s\";",
156                  "    }",
157                  "}");
158         compPass("public class EscapeSTextBlock {",
159                  "    public static void main(String... args) {",
160                  "        String xxx = \"\"\"",
161                  "                     \\s",
162                  "                     \"\"\";",
163                  "    }",
164                  "}");
165     }
166 
167     /*
168      * Check escape line terminator
169      */
test6()170     static void test6() {
171         String[] terminators = new String[] { "\n", "\r\n", "\r" };
172         for (String terminator : terminators) {
173             compPass("public class EscapeLineTerminator {",
174                      "    public static void main(String... args) {",
175                      "        String xxx = \"\"\"",
176                      "                     \\" + terminator +
177                      "                     \"\"\";",
178                      "    }",
179                      "}");
180         }
181     }
182 
183     /*
184      * Check incorrect escape line terminator cases
185      */
test7()186     static void test7() {
187         compFail("public class EscapeLineTerminatorChar {",
188                  "    public static void main(String... args) {",
189                  "        char xxx = '\\\n';",
190                  "    }",
191                  "}");
192         compFail("public class EscapeLineTerminatorString {",
193                  "    public static void main(String... args) {",
194                  "        String xxx = \"\\\n\";",
195                  "    }",
196                  "}");
197     }
198 
test8()199     static void test8() {
200         String code = "class C {\n" +
201                       "\n" +
202                       "    void x() {\n" +
203                       "        String s = \"\"\"\n" +
204                       "\n" +
205                       "\"\"\";\n" +
206                       "    }\n" +
207                       "}\n";
208 
209         new JavacTask(TOOLBOX)
210             .sources(code)
211             .classpath(".")
212             .options("-encoding", "utf8", "-Xlint")
213             .run();
214      }
215 
216     /*
217      * Test source for successful compile.
218      */
compPass(String source)219     static void compPass(String source) {
220         String output = new JavacTask(TOOLBOX)
221                 .sources(source)
222                 .classpath(".")
223                 .options("-encoding", "utf8")
224                 .run()
225                 .writeAll()
226                 .getOutput(Task.OutputKind.DIRECT);
227 
228         if (output.contains("compiler.err")) {
229             throw new RuntimeException("Error detected");
230         }
231     }
232 
compPass(String... lines)233     static void compPass(String... lines) {
234         compPass(String.join("\n", lines) + "\n");
235     }
236 
237     /*
238      * Test source for unsuccessful compile and specific error.
239      */
compFail(String source)240     static void compFail(String source)  {
241         String errors = new JavacTask(TOOLBOX)
242                 .sources(source)
243                 .classpath(".")
244                 .options("-XDrawDiagnostics", "-encoding", "utf8")
245                 .run(Task.Expect.FAIL)
246                 .writeAll()
247                 .getOutput(Task.OutputKind.DIRECT);
248 
249         if (!errors.contains("compiler.err")) {
250             throw new RuntimeException("No error detected");
251         }
252     }
253 
compFail(String... lines)254     static void compFail(String... lines) {
255         compFail(String.join("\n", lines) + "\n");
256     }
257 }
258