Thu, 21 Feb 2013 14:43:51 -0800
8008405: Now that metafactory is in place, add javac lambda serialization tests
Summary: Tests part of original langtools serialization review.
Reviewed-by: mcimadamore
1 /*
2 * Copyright (c) 2012, 2013, 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 */
24 /*
25 * @test
26 * @bug 8006694
27 * @summary Automatic test for checking correctness of default super/this resolution
28 * temporarily workaround combo tests are causing time out in several platforms
29 * @library ../../lib
30 * @build JavacTestingAbstractThreadedTest
31 * @run main/othervm TestDefaultSuperCall
32 */
34 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
35 // see JDK-8006746
37 import java.net.URI;
38 import java.util.Arrays;
39 import java.util.ArrayList;
40 import java.util.List;
41 import javax.tools.Diagnostic;
42 import javax.tools.JavaFileObject;
43 import javax.tools.SimpleJavaFileObject;
45 import com.sun.source.util.JavacTask;
47 public class TestDefaultSuperCall
48 extends JavacTestingAbstractThreadedTest
49 implements Runnable {
51 enum InterfaceKind {
52 DEFAULT("interface A extends B { default void m() { } }"),
53 ABSTRACT("interface A extends B { void m(); }"),
54 NONE("interface A extends B { }");
56 String interfaceStr;
58 InterfaceKind(String interfaceStr) {
59 this.interfaceStr = interfaceStr;
60 }
62 boolean methodDefined() {
63 return this == DEFAULT;
64 }
65 }
67 enum PruneKind {
68 NO_PRUNE("interface C { }"),
69 PRUNE("interface C extends A { }");
71 boolean methodDefined(InterfaceKind ik) {
72 return this == PRUNE &&
73 ik.methodDefined();
74 }
76 String interfaceStr;
78 PruneKind(String interfaceStr) {
79 this.interfaceStr = interfaceStr;
80 }
81 }
83 enum QualifierKind {
84 DIRECT_1("C"),
85 DIRECT_2("A"),
86 INDIRECT("B"),
87 UNRELATED("E"),
88 ENCLOSING_1(null),
89 ENCLOSING_2(null);
91 String qualifierStr;
93 QualifierKind(String qualifierStr) {
94 this.qualifierStr = qualifierStr;
95 }
97 String getQualifier(Shape sh) {
98 switch (this) {
99 case ENCLOSING_1: return sh.enclosingAt(0);
100 case ENCLOSING_2: return sh.enclosingAt(1);
101 default:
102 return qualifierStr;
103 }
104 }
106 boolean isEnclosing() {
107 return this == ENCLOSING_1 ||
108 this == ENCLOSING_2;
109 }
111 boolean allowSuperCall(InterfaceKind ik, PruneKind pk) {
112 switch (this) {
113 case DIRECT_1:
114 return pk.methodDefined(ik);
115 case DIRECT_2:
116 return ik.methodDefined() && pk == PruneKind.NO_PRUNE;
117 default:
118 return false;
119 }
120 }
121 }
123 enum ExprKind {
124 THIS("this"),
125 SUPER("super");
127 String exprStr;
129 ExprKind(String exprStr) {
130 this.exprStr = exprStr;
131 }
132 }
134 enum ElementKind {
135 INTERFACE("interface #N { #B }", true),
136 INTERFACE_EXTENDS("interface #N extends A, C { #B }", true),
137 CLASS("class #N { #B }", false),
138 CLASS_EXTENDS("abstract class #N implements A, C { #B }", false),
139 STATIC_CLASS("static class #N { #B }", true),
140 STATIC_CLASS_EXTENDS("abstract static class #N implements A, C { #B }", true),
141 ANON_CLASS("new Object() { #B };", false),
142 METHOD("void test() { #B }", false),
143 STATIC_METHOD("static void test() { #B }", true),
144 DEFAULT_METHOD("default void test() { #B }", false);
146 String templateDecl;
147 boolean isStatic;
149 ElementKind(String templateDecl, boolean isStatic) {
150 this.templateDecl = templateDecl;
151 this.isStatic = isStatic;
152 }
154 boolean isClassDecl() {
155 switch(this) {
156 case METHOD:
157 case STATIC_METHOD:
158 case DEFAULT_METHOD:
159 return false;
160 default:
161 return true;
162 }
163 }
165 boolean isAllowedEnclosing(ElementKind ek, boolean isTop) {
166 switch (this) {
167 case CLASS:
168 case CLASS_EXTENDS:
169 //class is implicitly static inside interface, so skip this combo
170 return ek.isClassDecl() &&
171 ek != INTERFACE && ek != INTERFACE_EXTENDS;
172 case ANON_CLASS:
173 return !ek.isClassDecl();
174 case METHOD:
175 return ek == CLASS || ek == CLASS_EXTENDS ||
176 ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS ||
177 ek == ANON_CLASS;
178 case INTERFACE:
179 case INTERFACE_EXTENDS:
180 case STATIC_CLASS:
181 case STATIC_CLASS_EXTENDS:
182 case STATIC_METHOD:
183 return (isTop && (ek == CLASS || ek == CLASS_EXTENDS)) ||
184 ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS;
185 case DEFAULT_METHOD:
186 return ek == INTERFACE || ek == INTERFACE_EXTENDS;
187 default:
188 throw new AssertionError("Bad enclosing element kind" + this);
189 }
190 }
192 boolean isAllowedTop() {
193 switch (this) {
194 case CLASS:
195 case CLASS_EXTENDS:
196 case INTERFACE:
197 case INTERFACE_EXTENDS:
198 return true;
199 default:
200 return false;
201 }
202 }
204 boolean hasSuper() {
205 return this == INTERFACE_EXTENDS ||
206 this == STATIC_CLASS_EXTENDS ||
207 this == CLASS_EXTENDS;
208 }
209 }
211 static class Shape {
213 String shapeStr;
214 List<ElementKind> enclosingElements;
215 List<String> enclosingNames;
216 List<String> elementsWithMethod;
218 Shape(ElementKind... elements) {
219 enclosingElements = new ArrayList<>();
220 enclosingNames = new ArrayList<>();
221 elementsWithMethod = new ArrayList<>();
222 int count = 0;
223 String prevName = null;
224 for (ElementKind ek : elements) {
225 String name = "name"+count++;
226 if (ek.isStatic) {
227 enclosingElements = new ArrayList<>();
228 enclosingNames = new ArrayList<>();
229 }
230 if (ek.isClassDecl()) {
231 enclosingElements.add(ek);
232 enclosingNames.add(name);
233 } else {
234 elementsWithMethod.add(prevName);
235 }
236 String element = ek.templateDecl.replaceAll("#N", name);
237 shapeStr = shapeStr ==
238 null ? element : shapeStr.replaceAll("#B", element);
239 prevName = name;
240 }
241 }
243 String getShape(QualifierKind qk, ExprKind ek) {
244 String methName = ek == ExprKind.THIS ? "test" : "m";
245 String call = qk.getQualifier(this) + "." +
246 ek.exprStr + "." + methName + "();";
247 return shapeStr.replaceAll("#B", call);
248 }
250 String enclosingAt(int index) {
251 return index < enclosingNames.size() ?
252 enclosingNames.get(index) : "BAD";
253 }
254 }
256 public static void main(String... args) throws Exception {
257 for (InterfaceKind ik : InterfaceKind.values()) {
258 for (PruneKind pk : PruneKind.values()) {
259 for (ElementKind ek1 : ElementKind.values()) {
260 if (!ek1.isAllowedTop()) continue;
261 for (ElementKind ek2 : ElementKind.values()) {
262 if (!ek2.isAllowedEnclosing(ek1, true)) continue;
263 for (ElementKind ek3 : ElementKind.values()) {
264 if (!ek3.isAllowedEnclosing(ek2, false)) continue;
265 for (ElementKind ek4 : ElementKind.values()) {
266 if (!ek4.isAllowedEnclosing(ek3, false)) continue;
267 for (ElementKind ek5 : ElementKind.values()) {
268 if (!ek5.isAllowedEnclosing(ek4, false) ||
269 ek5.isClassDecl()) continue;
270 for (QualifierKind qk : QualifierKind.values()) {
271 for (ExprKind ek : ExprKind.values()) {
272 pool.execute(
273 new TestDefaultSuperCall(ik, pk,
274 new Shape(ek1, ek2, ek3,
275 ek4, ek5), qk, ek));
276 }
277 }
278 }
279 }
280 }
281 }
282 }
283 }
284 }
286 checkAfterExec();
287 }
289 InterfaceKind ik;
290 PruneKind pk;
291 Shape sh;
292 QualifierKind qk;
293 ExprKind ek;
294 JavaSource source;
295 DiagnosticChecker diagChecker;
297 TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh,
298 QualifierKind qk, ExprKind ek) {
299 this.ik = ik;
300 this.pk = pk;
301 this.sh = sh;
302 this.qk = qk;
303 this.ek = ek;
304 this.source = new JavaSource();
305 this.diagChecker = new DiagnosticChecker();
306 }
308 class JavaSource extends SimpleJavaFileObject {
310 String template = "interface E {}\n" +
311 "interface B { }\n" +
312 "#I\n" +
313 "#P\n" +
314 "#C";
316 String source;
318 public JavaSource() {
319 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
320 source = template.replaceAll("#I", ik.interfaceStr)
321 .replaceAll("#P", pk.interfaceStr)
322 .replaceAll("#C", sh.getShape(qk, ek));
323 }
325 @Override
326 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
327 return source;
328 }
329 }
331 public void run() {
332 JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
333 null, null, Arrays.asList(source));
334 try {
335 ct.analyze();
336 } catch (Throwable ex) {
337 processException(ex);
338 return;
339 }
340 check();
341 }
343 void check() {
344 boolean errorExpected = false;
346 boolean badEnclosing = false;
347 boolean badThis = false;
348 boolean badSuper = false;
350 if (qk == QualifierKind.ENCLOSING_1 &&
351 sh.enclosingNames.size() < 1) {
352 errorExpected |= true;
353 badEnclosing = true;
354 }
356 if (qk == QualifierKind.ENCLOSING_2 &&
357 sh.enclosingNames.size() < 2) {
358 errorExpected |= true;
359 badEnclosing = true;
360 }
362 if (ek == ExprKind.THIS) {
363 boolean found = false;
364 for (int i = 0; i < sh.enclosingElements.size(); i++) {
365 if (sh.enclosingElements.get(i) == ElementKind.ANON_CLASS) continue;
366 if (sh.enclosingNames.get(i).equals(qk.getQualifier(sh))) {
367 found = sh.elementsWithMethod.contains(sh.enclosingNames.get(i));
368 break;
369 }
370 }
371 errorExpected |= !found;
372 if (!found) {
373 badThis = true;
374 }
375 }
377 if (ek == ExprKind.SUPER) {
379 int lastIdx = sh.enclosingElements.size() - 1;
380 boolean found = lastIdx == -1 ? false :
381 sh.enclosingElements.get(lastIdx).hasSuper() &&
382 qk.allowSuperCall(ik, pk);
384 errorExpected |= !found;
385 if (!found) {
386 badSuper = true;
387 }
388 }
390 checkCount.incrementAndGet();
391 if (diagChecker.errorFound != errorExpected) {
392 throw new AssertionError("Problem when compiling source:\n" +
393 source.getCharContent(true) +
394 "\nenclosingElems: " + sh.enclosingElements +
395 "\nenclosingNames: " + sh.enclosingNames +
396 "\nelementsWithMethod: " + sh.elementsWithMethod +
397 "\nbad encl: " + badEnclosing +
398 "\nbad this: " + badThis +
399 "\nbad super: " + badSuper +
400 "\nqual kind: " + qk +
401 "\nfound error: " + diagChecker.errorFound);
402 }
403 }
405 static class DiagnosticChecker
406 implements javax.tools.DiagnosticListener<JavaFileObject> {
408 boolean errorFound;
410 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
411 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
412 errorFound = true;
413 }
414 }
415 }
417 }