test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 */
aoqi@0 23
aoqi@0 24 /*
aoqi@0 25 * @test
aoqi@0 26 * @bug 7192246 8006694
aoqi@0 27 * @summary Automatic test for checking correctness of default super/this resolution
aoqi@0 28 * temporarily workaround combo tests are causing time out in several platforms
aoqi@0 29 * @library ../../lib
aoqi@0 30 * @build JavacTestingAbstractThreadedTest
aoqi@0 31 * @run main/othervm TestDefaultSuperCall
aoqi@0 32 */
aoqi@0 33
aoqi@0 34 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
aoqi@0 35 // see JDK-8006746
aoqi@0 36
aoqi@0 37 import java.net.URI;
aoqi@0 38 import java.util.Arrays;
aoqi@0 39 import java.util.ArrayList;
aoqi@0 40 import java.util.List;
aoqi@0 41 import javax.tools.Diagnostic;
aoqi@0 42 import javax.tools.JavaFileObject;
aoqi@0 43 import javax.tools.SimpleJavaFileObject;
aoqi@0 44
aoqi@0 45 import com.sun.source.util.JavacTask;
aoqi@0 46
aoqi@0 47 public class TestDefaultSuperCall
aoqi@0 48 extends JavacTestingAbstractThreadedTest
aoqi@0 49 implements Runnable {
aoqi@0 50
aoqi@0 51 enum InterfaceKind {
aoqi@0 52 DEFAULT("interface A extends B { default void m() { } }"),
aoqi@0 53 ABSTRACT("interface A extends B { void m(); }"),
aoqi@0 54 NONE("interface A extends B { }");
aoqi@0 55
aoqi@0 56 String interfaceStr;
aoqi@0 57
aoqi@0 58 InterfaceKind(String interfaceStr) {
aoqi@0 59 this.interfaceStr = interfaceStr;
aoqi@0 60 }
aoqi@0 61
aoqi@0 62 boolean methodDefined() {
aoqi@0 63 return this == DEFAULT;
aoqi@0 64 }
aoqi@0 65 }
aoqi@0 66
aoqi@0 67 enum PruneKind {
aoqi@0 68 NO_PRUNE("interface C { }"),
aoqi@0 69 PRUNE("interface C extends A { }");
aoqi@0 70
aoqi@0 71 boolean methodDefined(InterfaceKind ik) {
aoqi@0 72 return this == PRUNE &&
aoqi@0 73 ik.methodDefined();
aoqi@0 74 }
aoqi@0 75
aoqi@0 76 String interfaceStr;
aoqi@0 77
aoqi@0 78 PruneKind(String interfaceStr) {
aoqi@0 79 this.interfaceStr = interfaceStr;
aoqi@0 80 }
aoqi@0 81 }
aoqi@0 82
aoqi@0 83 enum QualifierKind {
aoqi@0 84 DIRECT_1("C"),
aoqi@0 85 DIRECT_2("A"),
aoqi@0 86 INDIRECT("B"),
aoqi@0 87 UNRELATED("E"),
aoqi@0 88 ENCLOSING_1(null),
aoqi@0 89 ENCLOSING_2(null);
aoqi@0 90
aoqi@0 91 String qualifierStr;
aoqi@0 92
aoqi@0 93 QualifierKind(String qualifierStr) {
aoqi@0 94 this.qualifierStr = qualifierStr;
aoqi@0 95 }
aoqi@0 96
aoqi@0 97 String getQualifier(Shape sh) {
aoqi@0 98 switch (this) {
aoqi@0 99 case ENCLOSING_1: return sh.enclosingAt(0);
aoqi@0 100 case ENCLOSING_2: return sh.enclosingAt(1);
aoqi@0 101 default:
aoqi@0 102 return qualifierStr;
aoqi@0 103 }
aoqi@0 104 }
aoqi@0 105
aoqi@0 106 boolean isEnclosing() {
aoqi@0 107 return this == ENCLOSING_1 ||
aoqi@0 108 this == ENCLOSING_2;
aoqi@0 109 }
aoqi@0 110
aoqi@0 111 boolean allowSuperCall(InterfaceKind ik, PruneKind pk) {
aoqi@0 112 switch (this) {
aoqi@0 113 case DIRECT_1:
aoqi@0 114 return pk.methodDefined(ik);
aoqi@0 115 case DIRECT_2:
aoqi@0 116 return ik.methodDefined() && pk == PruneKind.NO_PRUNE;
aoqi@0 117 default:
aoqi@0 118 return false;
aoqi@0 119 }
aoqi@0 120 }
aoqi@0 121 }
aoqi@0 122
aoqi@0 123 enum ExprKind {
aoqi@0 124 THIS("this"),
aoqi@0 125 SUPER("super");
aoqi@0 126
aoqi@0 127 String exprStr;
aoqi@0 128
aoqi@0 129 ExprKind(String exprStr) {
aoqi@0 130 this.exprStr = exprStr;
aoqi@0 131 }
aoqi@0 132 }
aoqi@0 133
aoqi@0 134 enum ElementKind {
aoqi@0 135 INTERFACE("interface #N { #B }", true),
aoqi@0 136 INTERFACE_EXTENDS("interface #N extends A, C { #B }", true),
aoqi@0 137 CLASS("class #N { #B }", false),
aoqi@0 138 CLASS_EXTENDS("abstract class #N implements A, C { #B }", false),
aoqi@0 139 STATIC_CLASS("static class #N { #B }", true),
aoqi@0 140 STATIC_CLASS_EXTENDS("abstract static class #N implements A, C { #B }", true),
aoqi@0 141 ANON_CLASS("new Object() { #B };", false),
aoqi@0 142 METHOD("void test() { #B }", false),
aoqi@0 143 STATIC_METHOD("static void test() { #B }", true),
aoqi@0 144 DEFAULT_METHOD("default void test() { #B }", false);
aoqi@0 145
aoqi@0 146 String templateDecl;
aoqi@0 147 boolean isStatic;
aoqi@0 148
aoqi@0 149 ElementKind(String templateDecl, boolean isStatic) {
aoqi@0 150 this.templateDecl = templateDecl;
aoqi@0 151 this.isStatic = isStatic;
aoqi@0 152 }
aoqi@0 153
aoqi@0 154 boolean isClassDecl() {
aoqi@0 155 switch(this) {
aoqi@0 156 case METHOD:
aoqi@0 157 case STATIC_METHOD:
aoqi@0 158 case DEFAULT_METHOD:
aoqi@0 159 return false;
aoqi@0 160 default:
aoqi@0 161 return true;
aoqi@0 162 }
aoqi@0 163 }
aoqi@0 164
aoqi@0 165 boolean isAllowedEnclosing(ElementKind ek, boolean isTop) {
aoqi@0 166 switch (this) {
aoqi@0 167 case CLASS:
aoqi@0 168 case CLASS_EXTENDS:
aoqi@0 169 //class is implicitly static inside interface, so skip this combo
aoqi@0 170 return ek.isClassDecl() &&
aoqi@0 171 ek != INTERFACE && ek != INTERFACE_EXTENDS;
aoqi@0 172 case ANON_CLASS:
aoqi@0 173 return !ek.isClassDecl();
aoqi@0 174 case METHOD:
aoqi@0 175 return ek == CLASS || ek == CLASS_EXTENDS ||
aoqi@0 176 ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS ||
aoqi@0 177 ek == ANON_CLASS;
aoqi@0 178 case INTERFACE:
aoqi@0 179 case INTERFACE_EXTENDS:
aoqi@0 180 case STATIC_CLASS:
aoqi@0 181 case STATIC_CLASS_EXTENDS:
aoqi@0 182 case STATIC_METHOD:
aoqi@0 183 return (isTop && (ek == CLASS || ek == CLASS_EXTENDS)) ||
aoqi@0 184 ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS;
aoqi@0 185 case DEFAULT_METHOD:
aoqi@0 186 return ek == INTERFACE || ek == INTERFACE_EXTENDS;
aoqi@0 187 default:
aoqi@0 188 throw new AssertionError("Bad enclosing element kind" + this);
aoqi@0 189 }
aoqi@0 190 }
aoqi@0 191
aoqi@0 192 boolean isAllowedTop() {
aoqi@0 193 switch (this) {
aoqi@0 194 case CLASS:
aoqi@0 195 case CLASS_EXTENDS:
aoqi@0 196 case INTERFACE:
aoqi@0 197 case INTERFACE_EXTENDS:
aoqi@0 198 return true;
aoqi@0 199 default:
aoqi@0 200 return false;
aoqi@0 201 }
aoqi@0 202 }
aoqi@0 203
aoqi@0 204 boolean hasSuper() {
aoqi@0 205 return this == INTERFACE_EXTENDS ||
aoqi@0 206 this == STATIC_CLASS_EXTENDS ||
aoqi@0 207 this == CLASS_EXTENDS;
aoqi@0 208 }
aoqi@0 209 }
aoqi@0 210
aoqi@0 211 static class Shape {
aoqi@0 212
aoqi@0 213 String shapeStr;
aoqi@0 214 List<ElementKind> enclosingElements;
aoqi@0 215 List<String> enclosingNames;
aoqi@0 216 List<String> elementsWithMethod;
aoqi@0 217
aoqi@0 218 Shape(ElementKind... elements) {
aoqi@0 219 enclosingElements = new ArrayList<>();
aoqi@0 220 enclosingNames = new ArrayList<>();
aoqi@0 221 elementsWithMethod = new ArrayList<>();
aoqi@0 222 int count = 0;
aoqi@0 223 String prevName = null;
aoqi@0 224 for (ElementKind ek : elements) {
aoqi@0 225 String name = "name"+count++;
aoqi@0 226 if (ek.isStatic) {
aoqi@0 227 enclosingElements = new ArrayList<>();
aoqi@0 228 enclosingNames = new ArrayList<>();
aoqi@0 229 }
aoqi@0 230 if (ek.isClassDecl()) {
aoqi@0 231 enclosingElements.add(ek);
aoqi@0 232 enclosingNames.add(name);
aoqi@0 233 } else {
aoqi@0 234 elementsWithMethod.add(prevName);
aoqi@0 235 }
aoqi@0 236 String element = ek.templateDecl.replaceAll("#N", name);
aoqi@0 237 shapeStr = shapeStr ==
aoqi@0 238 null ? element : shapeStr.replaceAll("#B", element);
aoqi@0 239 prevName = name;
aoqi@0 240 }
aoqi@0 241 }
aoqi@0 242
aoqi@0 243 String getShape(QualifierKind qk, ExprKind ek) {
aoqi@0 244 String methName = ek == ExprKind.THIS ? "test" : "m";
aoqi@0 245 String call = qk.getQualifier(this) + "." +
aoqi@0 246 ek.exprStr + "." + methName + "();";
aoqi@0 247 return shapeStr.replaceAll("#B", call);
aoqi@0 248 }
aoqi@0 249
aoqi@0 250 String enclosingAt(int index) {
aoqi@0 251 return index < enclosingNames.size() ?
aoqi@0 252 enclosingNames.get(index) : "BAD";
aoqi@0 253 }
aoqi@0 254 }
aoqi@0 255
aoqi@0 256 public static void main(String... args) throws Exception {
aoqi@0 257 for (InterfaceKind ik : InterfaceKind.values()) {
aoqi@0 258 for (PruneKind pk : PruneKind.values()) {
aoqi@0 259 for (ElementKind ek1 : ElementKind.values()) {
aoqi@0 260 if (!ek1.isAllowedTop()) continue;
aoqi@0 261 for (ElementKind ek2 : ElementKind.values()) {
aoqi@0 262 if (!ek2.isAllowedEnclosing(ek1, true)) continue;
aoqi@0 263 for (ElementKind ek3 : ElementKind.values()) {
aoqi@0 264 if (!ek3.isAllowedEnclosing(ek2, false)) continue;
aoqi@0 265 for (ElementKind ek4 : ElementKind.values()) {
aoqi@0 266 if (!ek4.isAllowedEnclosing(ek3, false)) continue;
aoqi@0 267 for (ElementKind ek5 : ElementKind.values()) {
aoqi@0 268 if (!ek5.isAllowedEnclosing(ek4, false) ||
aoqi@0 269 ek5.isClassDecl()) continue;
aoqi@0 270 for (QualifierKind qk : QualifierKind.values()) {
aoqi@0 271 for (ExprKind ek : ExprKind.values()) {
aoqi@0 272 pool.execute(
aoqi@0 273 new TestDefaultSuperCall(ik, pk,
aoqi@0 274 new Shape(ek1, ek2, ek3,
aoqi@0 275 ek4, ek5), qk, ek));
aoqi@0 276 }
aoqi@0 277 }
aoqi@0 278 }
aoqi@0 279 }
aoqi@0 280 }
aoqi@0 281 }
aoqi@0 282 }
aoqi@0 283 }
aoqi@0 284 }
aoqi@0 285
aoqi@0 286 checkAfterExec();
aoqi@0 287 }
aoqi@0 288
aoqi@0 289 InterfaceKind ik;
aoqi@0 290 PruneKind pk;
aoqi@0 291 Shape sh;
aoqi@0 292 QualifierKind qk;
aoqi@0 293 ExprKind ek;
aoqi@0 294 JavaSource source;
aoqi@0 295 DiagnosticChecker diagChecker;
aoqi@0 296
aoqi@0 297 TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh,
aoqi@0 298 QualifierKind qk, ExprKind ek) {
aoqi@0 299 this.ik = ik;
aoqi@0 300 this.pk = pk;
aoqi@0 301 this.sh = sh;
aoqi@0 302 this.qk = qk;
aoqi@0 303 this.ek = ek;
aoqi@0 304 this.source = new JavaSource();
aoqi@0 305 this.diagChecker = new DiagnosticChecker();
aoqi@0 306 }
aoqi@0 307
aoqi@0 308 class JavaSource extends SimpleJavaFileObject {
aoqi@0 309
aoqi@0 310 String template = "interface E {}\n" +
aoqi@0 311 "interface B { }\n" +
aoqi@0 312 "#I\n" +
aoqi@0 313 "#P\n" +
aoqi@0 314 "#C";
aoqi@0 315
aoqi@0 316 String source;
aoqi@0 317
aoqi@0 318 public JavaSource() {
aoqi@0 319 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
aoqi@0 320 source = template.replaceAll("#I", ik.interfaceStr)
aoqi@0 321 .replaceAll("#P", pk.interfaceStr)
aoqi@0 322 .replaceAll("#C", sh.getShape(qk, ek));
aoqi@0 323 }
aoqi@0 324
aoqi@0 325 @Override
aoqi@0 326 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
aoqi@0 327 return source;
aoqi@0 328 }
aoqi@0 329 }
aoqi@0 330
aoqi@0 331 public void run() {
aoqi@0 332 JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
aoqi@0 333 null, null, Arrays.asList(source));
aoqi@0 334 try {
aoqi@0 335 ct.analyze();
aoqi@0 336 } catch (Throwable ex) {
aoqi@0 337 processException(ex);
aoqi@0 338 return;
aoqi@0 339 }
aoqi@0 340 check();
aoqi@0 341 }
aoqi@0 342
aoqi@0 343 void check() {
aoqi@0 344 boolean errorExpected = false;
aoqi@0 345
aoqi@0 346 boolean badEnclosing = false;
aoqi@0 347 boolean badThis = false;
aoqi@0 348 boolean badSuper = false;
aoqi@0 349
aoqi@0 350 if (qk == QualifierKind.ENCLOSING_1 &&
aoqi@0 351 sh.enclosingNames.size() < 1) {
aoqi@0 352 errorExpected |= true;
aoqi@0 353 badEnclosing = true;
aoqi@0 354 }
aoqi@0 355
aoqi@0 356 if (qk == QualifierKind.ENCLOSING_2 &&
aoqi@0 357 sh.enclosingNames.size() < 2) {
aoqi@0 358 errorExpected |= true;
aoqi@0 359 badEnclosing = true;
aoqi@0 360 }
aoqi@0 361
aoqi@0 362 if (ek == ExprKind.THIS) {
aoqi@0 363 boolean found = false;
aoqi@0 364 for (int i = 0; i < sh.enclosingElements.size(); i++) {
aoqi@0 365 if (sh.enclosingElements.get(i) == ElementKind.ANON_CLASS) continue;
aoqi@0 366 if (sh.enclosingNames.get(i).equals(qk.getQualifier(sh))) {
aoqi@0 367 found = sh.elementsWithMethod.contains(sh.enclosingNames.get(i));
aoqi@0 368 break;
aoqi@0 369 }
aoqi@0 370 }
aoqi@0 371 errorExpected |= !found;
aoqi@0 372 if (!found) {
aoqi@0 373 badThis = true;
aoqi@0 374 }
aoqi@0 375 }
aoqi@0 376
aoqi@0 377 if (ek == ExprKind.SUPER) {
aoqi@0 378
aoqi@0 379 int lastIdx = sh.enclosingElements.size() - 1;
aoqi@0 380 boolean found = lastIdx == -1 ? false :
aoqi@0 381 sh.enclosingElements.get(lastIdx).hasSuper() &&
aoqi@0 382 qk.allowSuperCall(ik, pk);
aoqi@0 383
aoqi@0 384 errorExpected |= !found;
aoqi@0 385 if (!found) {
aoqi@0 386 badSuper = true;
aoqi@0 387 }
aoqi@0 388 }
aoqi@0 389
aoqi@0 390 checkCount.incrementAndGet();
aoqi@0 391 if (diagChecker.errorFound != errorExpected) {
aoqi@0 392 throw new AssertionError("Problem when compiling source:\n" +
aoqi@0 393 source.getCharContent(true) +
aoqi@0 394 "\nenclosingElems: " + sh.enclosingElements +
aoqi@0 395 "\nenclosingNames: " + sh.enclosingNames +
aoqi@0 396 "\nelementsWithMethod: " + sh.elementsWithMethod +
aoqi@0 397 "\nbad encl: " + badEnclosing +
aoqi@0 398 "\nbad this: " + badThis +
aoqi@0 399 "\nbad super: " + badSuper +
aoqi@0 400 "\nqual kind: " + qk +
aoqi@0 401 "\nfound error: " + diagChecker.errorFound);
aoqi@0 402 }
aoqi@0 403 }
aoqi@0 404
aoqi@0 405 static class DiagnosticChecker
aoqi@0 406 implements javax.tools.DiagnosticListener<JavaFileObject> {
aoqi@0 407
aoqi@0 408 boolean errorFound;
aoqi@0 409
aoqi@0 410 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
aoqi@0 411 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
aoqi@0 412 errorFound = true;
aoqi@0 413 }
aoqi@0 414 }
aoqi@0 415 }
aoqi@0 416
aoqi@0 417 }

mercurial