T6888367.java revision 3222:94cfc50c1b8a
1238106Sdes/* 2238106Sdes * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. 3238106Sdes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4238106Sdes * 5238106Sdes * This code is free software; you can redistribute it and/or modify it 6238106Sdes * under the terms of the GNU General Public License version 2 only, as 7238106Sdes * published by the Free Software Foundation. 8238106Sdes * 9238106Sdes * This code is distributed in the hope that it will be useful, but WITHOUT 10238106Sdes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11238106Sdes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12238106Sdes * version 2 for more details (a copy is included in the LICENSE file that 13238106Sdes * accompanied this code). 14238106Sdes * 15238106Sdes * You should have received a copy of the GNU General Public License version 16238106Sdes * 2 along with this work; if not, write to the Free Software Foundation, 17238106Sdes * 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 24import java.io.*; 25import java.net.*; 26import java.util.*; 27import com.sun.tools.classfile.*; 28import com.sun.tools.classfile.Type.ArrayType; 29import com.sun.tools.classfile.Type.ClassSigType; 30import com.sun.tools.classfile.Type.ClassType; 31import com.sun.tools.classfile.Type.MethodType; 32import com.sun.tools.classfile.Type.SimpleType; 33import com.sun.tools.classfile.Type.TypeParamType; 34import com.sun.tools.classfile.Type.WildcardType; 35 36/* 37 * @test 38 * @bug 6888367 39 * @summary classfile library parses signature attributes incorrectly 40 * @modules jdk.jdeps/com.sun.tools.classfile 41 */ 42 43/* 44 * This test is a pretty detailed test both of javac signature generation and classfile 45 * signature parsing. The first part of the test tests all the examples given in the 46 * second part of the test. Each example comes with one or two annotations, @Desc, @Sig, 47 * for the descriptor and signature of the annotated declaration. Annotations are 48 * provided whenever the annotated item is expected to have a corresponding value. 49 * Each annotation has two argument values. The first arg is the expected value of the 50 * descriptor/signature as found in the class file. This value is mostly for documentation 51 * purposes in reading the test. The second value is the rendering of the descriptor or 52 * signature using a custom Type visitor that explicitly includes an indication of the 53 * Type classes being used to represent the descriptor/signature. Thus we test 54 * that the descriptor/signature is being parsed into the expected type tree structure. 55 */ 56public class T6888367 { 57 58 public static void main(String... args) throws Exception { 59 new T6888367().run(); 60 } 61 62 public void run() throws Exception { 63 ClassFile cf = getClassFile("Test"); 64 65 testFields(cf); 66 testMethods(cf); 67 testInnerClasses(cf); // recursive 68 69 if (errors > 0) 70 throw new Exception(errors + " errors found"); 71 } 72 73 void testFields(ClassFile cf) throws Exception { 74 String cn = cf.getName(); 75 ConstantPool cp = cf.constant_pool; 76 for (Field f: cf.fields) { 77 test("field " + cn + "." + f.getName(cp), f.descriptor, f.attributes, cp); 78 } 79 } 80 81 void testMethods(ClassFile cf) throws Exception { 82 String cn = cf.getName(); 83 ConstantPool cp = cf.constant_pool; 84 for (Method m: cf.methods) { 85 test("method " + cn + "." + m.getName(cp), m.descriptor, m.attributes, cp); 86 } 87 } 88 89 void testInnerClasses(ClassFile cf) throws Exception { 90 ConstantPool cp = cf.constant_pool; 91 InnerClasses_attribute ic = 92 (InnerClasses_attribute) cf.attributes.get(Attribute.InnerClasses); 93 for (InnerClasses_attribute.Info info: ic.classes) { 94 String outerClassName = cp.getClassInfo(info.outer_class_info_index).getName(); 95 if (!outerClassName.equals(cf.getName())) { 96 continue; 97 } 98 String innerClassName = cp.getClassInfo(info.inner_class_info_index).getName(); 99 ClassFile icf = getClassFile(innerClassName); 100 test("class " + innerClassName, null, icf.attributes, icf.constant_pool); 101 testInnerClasses(icf); 102 } 103 } 104 105 void test(String name, Descriptor desc, Attributes attrs, ConstantPool cp) 106 throws Exception { 107 AnnotValues d = getDescValue(attrs, cp); 108 AnnotValues s = getSigValue(attrs, cp); 109 if (d == null && s == null) // not a test field or method if no @Desc or @Sig given 110 return; 111 112 System.err.println(name); 113 114 if (desc != null) { 115 System.err.println(" descriptor: " + desc.getValue(cp)); 116 checkEqual(d.raw, desc.getValue(cp)); 117 Type dt = new Signature(desc.index).getType(cp); 118 checkEqual(d.type, tp.print(dt)); 119 } 120 121 Signature_attribute sa = (Signature_attribute) attrs.get(Attribute.Signature); 122 if (sa != null) 123 System.err.println(" signature: " + sa.getSignature(cp)); 124 125 if (s != null || sa != null) { 126 if (s != null && sa != null) { 127 checkEqual(s.raw, sa.getSignature(cp)); 128 Type st = new Signature(sa.signature_index).getType(cp); 129 checkEqual(s.type, tp.print(st)); 130 } else if (s != null) 131 error("@Sig annotation found but not Signature attribute"); 132 else 133 error("Signature attribute found but no @Sig annotation"); 134 } 135 136 System.err.println(); 137 } 138 139 140 ClassFile getClassFile(String name) throws IOException, ConstantPoolException { 141 URL url = getClass().getResource(name + ".class"); 142 InputStream in = url.openStream(); 143 try { 144 return ClassFile.read(in); 145 } finally { 146 in.close(); 147 } 148 } 149 150 AnnotValues getDescValue(Attributes attrs, ConstantPool cp) throws Exception { 151 return getAnnotValues(Desc.class.getName(), attrs, cp); 152 } 153 154 AnnotValues getSigValue(Attributes attrs, ConstantPool cp) throws Exception { 155 return getAnnotValues(Sig.class.getName(), attrs, cp); 156 } 157 158 static class AnnotValues { 159 AnnotValues(String raw, String type) { 160 this.raw = raw; 161 this.type = type; 162 } 163 final String raw; 164 final String type; 165 } 166 167 AnnotValues getAnnotValues(String annotName, Attributes attrs, ConstantPool cp) 168 throws Exception { 169 RuntimeInvisibleAnnotations_attribute annots = 170 (RuntimeInvisibleAnnotations_attribute)attrs.get(Attribute.RuntimeInvisibleAnnotations); 171 if (annots != null) { 172 for (Annotation a: annots.annotations) { 173 if (cp.getUTF8Value(a.type_index).equals("L" + annotName + ";")) { 174 Annotation.Primitive_element_value pv0 = 175 (Annotation.Primitive_element_value) a.element_value_pairs[0].value; 176 Annotation.Primitive_element_value pv1 = 177 (Annotation.Primitive_element_value) a.element_value_pairs[1].value; 178 return new AnnotValues( 179 cp.getUTF8Value(pv0.const_value_index), 180 cp.getUTF8Value(pv1.const_value_index)); 181 } 182 } 183 } 184 return null; 185 186 } 187 188 void checkEqual(String expect, String found) { 189 if (!(expect == null ? found == null : expect.equals(found))) { 190 System.err.println("expected: " + expect); 191 System.err.println(" found: " + found); 192 error("unexpected values found"); 193 } 194 } 195 196 void error(String msg) { 197 System.err.println("error: " + msg); 198 errors++; 199 } 200 201 int errors; 202 203 TypePrinter tp = new TypePrinter(); 204 205 class TypePrinter implements Type.Visitor<String,Void> { 206 String print(Type t) { 207 return t == null ? null : t.accept(this, null); 208 } 209 String print(String pre, List<? extends Type> ts, String post) { 210 if (ts == null) 211 return null; 212 StringBuilder sb = new StringBuilder(); 213 sb.append(pre); 214 String sep = ""; 215 for (Type t: ts) { 216 sb.append(sep); 217 sb.append(print(t)); 218 sep = ","; 219 } 220 sb.append(post); 221 return sb.toString(); 222 } 223 224 public String visitSimpleType(SimpleType type, Void p) { 225 return "S{" + type.name + "}"; 226 } 227 228 public String visitArrayType(ArrayType type, Void p) { 229 return "A{" + print(type.elemType) + "}"; 230 } 231 232 public String visitMethodType(MethodType type, Void p) { 233 StringBuilder sb = new StringBuilder(); 234 sb.append("M{"); 235 if (type.typeParamTypes != null) 236 sb.append(print("<", type.typeParamTypes, ">")); 237 sb.append(print(type.returnType)); 238 sb.append(print("(", type.paramTypes, ")")); 239 if (type.throwsTypes != null) 240 sb.append(print("", type.throwsTypes, "")); 241 sb.append("}"); 242 return sb.toString(); 243 } 244 245 public String visitClassSigType(ClassSigType type, Void p) { 246 StringBuilder sb = new StringBuilder(); 247 sb.append("CS{"); 248 if (type.typeParamTypes != null) 249 sb.append(print("<", type.typeParamTypes, ">")); 250 sb.append(print(type.superclassType)); 251 if (type.superinterfaceTypes != null) 252 sb.append(print("i(", type.superinterfaceTypes, ")")); 253 sb.append("}"); 254 return sb.toString(); 255 } 256 257 public String visitClassType(ClassType type, Void p) { 258 StringBuilder sb = new StringBuilder(); 259 sb.append("C{"); 260 if (type.outerType != null) { 261 sb.append(print(type.outerType)); 262 sb.append("."); 263 } 264 sb.append(type.name); 265 if (type.typeArgs != null) 266 sb.append(print("<", type.typeArgs, ">")); 267 sb.append("}"); 268 return sb.toString(); 269 } 270 271 public String visitTypeParamType(TypeParamType type, Void p) { 272 StringBuilder sb = new StringBuilder(); 273 sb.append("TA{"); 274 sb.append(type.name); 275 if (type.classBound != null) { 276 sb.append(":c"); 277 sb.append(print(type.classBound)); 278 } 279 if (type.interfaceBounds != null) 280 sb.append(print(":i", type.interfaceBounds, "")); 281 sb.append("}"); 282 return sb.toString(); 283 } 284 285 public String visitWildcardType(WildcardType type, Void p) { 286 switch (type.kind) { 287 case UNBOUNDED: 288 return "W{?}"; 289 case EXTENDS: 290 return "W{e," + print(type.boundType) + "}"; 291 case SUPER: 292 return "W{s," + print(type.boundType) + "}"; 293 default: 294 throw new AssertionError(); 295 } 296 } 297 298 }; 299} 300 301 302@interface Desc { 303 String d(); 304 String t(); 305} 306 307@interface Sig { 308 String s(); 309 String t(); 310} 311 312class Clss { } 313interface Intf { } 314class GenClss<T> { } 315 316class Test { 317 // fields 318 319 @Desc(d="Z", t="S{boolean}") 320 boolean z; 321 322 @Desc(d="B", t="S{byte}") 323 byte b; 324 325 @Desc(d="C", t="S{char}") 326 char c; 327 328 @Desc(d="D", t="S{double}") 329 double d; 330 331 @Desc(d="F", t="S{float}") 332 float f; 333 334 @Desc(d="I", t="S{int}") 335 int i; 336 337 @Desc(d="J", t="S{long}") 338 long l; 339 340 @Desc(d="S", t="S{short}") 341 short s; 342 343 @Desc(d="LClss;", t="C{Clss}") 344 Clss clss; 345 346 @Desc(d="LIntf;", t="C{Intf}") 347 Intf intf; 348 349 @Desc(d="[I", t="A{S{int}}") 350 int[] ai; 351 352 @Desc(d="[LClss;", t="A{C{Clss}}") 353 Clss[] aClss; 354 355 @Desc(d="LGenClss;", t="C{GenClss}") 356 @Sig(s="LGenClss<LClss;>;", t="C{GenClss<C{Clss}>}") 357 GenClss<Clss> genClass; 358 359 // methods, return types 360 361 @Desc(d="()V", t="M{S{void}()}") 362 void mv0() { } 363 364 @Desc(d="()I", t="M{S{int}()}") 365 int mi0() { return 0; } 366 367 @Desc(d="()LClss;", t="M{C{Clss}()}") 368 Clss mclss0() { return null; } 369 370 @Desc(d="()[I", t="M{A{S{int}}()}") 371 int[] mai0() { return null; } 372 373 @Desc(d="()[LClss;", t="M{A{C{Clss}}()}") 374 Clss[] maClss0() { return null; } 375 376 @Desc(d="()LGenClss;", t="M{C{GenClss}()}") 377 @Sig(s="()LGenClss<LClss;>;", t="M{C{GenClss<C{Clss}>}()}") 378 GenClss<Clss> mgenClss0() { return null; } 379 380 @Desc(d="()LGenClss;", t="M{C{GenClss}()}") 381 @Sig(s="()LGenClss<*>;", t="M{C{GenClss<W{?}>}()}") 382 GenClss<?> mgenClssW0() { return null; } 383 384 @Desc(d="()LGenClss;", t="M{C{GenClss}()}") 385 @Sig(s="()LGenClss<+LClss;>;", t="M{C{GenClss<W{e,C{Clss}}>}()}") 386 GenClss<? extends Clss> mgenClssWExtClss0() { return null; } 387 388 @Desc(d="()LGenClss;", t="M{C{GenClss}()}") 389 @Sig(s="()LGenClss<-LClss;>;", t="M{C{GenClss<W{s,C{Clss}}>}()}") 390 GenClss<? super Clss> mgenClssWSupClss0() { return null; } 391 392 @Desc(d="()Ljava/lang/Object;", t="M{C{java/lang/Object}()}") 393 @Sig(s="<T:Ljava/lang/Object;>()TT;", t="M{<TA{T:cC{java/lang/Object}}>S{T}()}") 394 <T> T mt0() { return null; } 395 396 @Desc(d="()LGenClss;", t="M{C{GenClss}()}") 397 @Sig(s="<T:Ljava/lang/Object;>()LGenClss<+TT;>;", 398 t="M{<TA{T:cC{java/lang/Object}}>C{GenClss<W{e,S{T}}>}()}") 399 <T> GenClss<? extends T> mgenClssWExtT0() { return null; } 400 401 @Desc(d="()LGenClss;", t="M{C{GenClss}()}") 402 @Sig(s="<T:Ljava/lang/Object;>()LGenClss<-TT;>;", t="M{<TA{T:cC{java/lang/Object}}>C{GenClss<W{s,S{T}}>}()}") 403 <T> GenClss<? super T> mgenClssWSupT0() { return null; } 404 405 // methods, arg types 406 407 @Desc(d="(I)V", t="M{S{void}(S{int})}") 408 void mi1(int arg) { } 409 410 @Desc(d="(LClss;)V", t="M{S{void}(C{Clss})}") 411 void mclss1(Clss arg) { } 412 413 @Desc(d="([I)V", t="M{S{void}(A{S{int}})}") 414 void mai1(int[] arg) { } 415 416 @Desc(d="([LClss;)V", t="M{S{void}(A{C{Clss}})}") 417 void maClss1(Clss[] arg) { } 418 419 @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") 420 @Sig(s="(LGenClss<LClss;>;)V", t="M{S{void}(C{GenClss<C{Clss}>})}") 421 void mgenClss1(GenClss<Clss> arg) { } 422 423 @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") 424 @Sig(s="(LGenClss<*>;)V", t="M{S{void}(C{GenClss<W{?}>})}") 425 void mgenClssW1(GenClss<?> arg) { } 426 427 @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") 428 @Sig(s="(LGenClss<+LClss;>;)V", t="M{S{void}(C{GenClss<W{e,C{Clss}}>})}") 429 void mgenClssWExtClss1(GenClss<? extends Clss> arg) { } 430 431 @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") 432 @Sig(s="(LGenClss<-LClss;>;)V", t="M{S{void}(C{GenClss<W{s,C{Clss}}>})}") 433 void mgenClssWSupClss1(GenClss<? super Clss> arg) { } 434 435 @Desc(d="(Ljava/lang/Object;)V", t="M{S{void}(C{java/lang/Object})}") 436 @Sig(s="<T:Ljava/lang/Object;>(TT;)V", 437 t="M{<TA{T:cC{java/lang/Object}}>S{void}(S{T})}") 438 <T> void mt1(T arg) { } 439 440 @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") 441 @Sig(s="<T:Ljava/lang/Object;>(LGenClss<+TT;>;)V", 442 t="M{<TA{T:cC{java/lang/Object}}>S{void}(C{GenClss<W{e,S{T}}>})}") 443 <T> void mgenClssWExtT1(GenClss<? extends T> arg) { } 444 445 @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") 446 @Sig(s="<T:Ljava/lang/Object;>(LGenClss<-TT;>;)V", 447 t="M{<TA{T:cC{java/lang/Object}}>S{void}(C{GenClss<W{s,S{T}}>})}") 448 <T> void mgenClssWSupT1(GenClss<? super T> arg) { } 449 450 // methods, throws 451 452 @Desc(d="()V", t="M{S{void}()}") 453 void m_E() throws Exception { } 454 455 @Desc(d="()V", t="M{S{void}()}") 456 @Sig(s="<T:Ljava/lang/Throwable;>()V^TT;", 457 t="M{<TA{T:cC{java/lang/Throwable}}>S{void}()S{T}}") 458 <T extends Throwable> void m_T() throws T { } 459 460 // inner classes 461 462 static class X { 463 // no sig 464 class P { } 465 466 @Sig(s="<TQ:Ljava/lang/Object;>LTest$X$P;", 467 t="CS{<TA{TQ:cC{java/lang/Object}}>C{Test$X$P}}") 468 class Q<TQ> extends P { } 469 470 @Sig(s="<TR:Ljava/lang/Object;>LTest$X$Q<TTR;>;", 471 t="CS{<TA{TR:cC{java/lang/Object}}>C{Test$X$Q<S{TR}>}}") 472 class R<TR> extends Q<TR> { } 473 } 474 475 @Sig(s="<TY:Ljava/lang/Object;>Ljava/lang/Object;", 476 t="CS{<TA{TY:cC{java/lang/Object}}>C{java/lang/Object}}") 477 static class Y<TY> { 478 // no sig 479 class P { } 480 481 @Sig(s="<TQ:Ljava/lang/Object;>LTest$Y<TTY;>.P;", 482 t="CS{<TA{TQ:cC{java/lang/Object}}>C{C{Test$Y<S{TY}>}.P}}") 483 class Q<TQ> extends P { } 484 485 @Sig(s="<TR:Ljava/lang/Object;>LTest$Y<TTY;>.Q<TTR;>;", 486 t="CS{<TA{TR:cC{java/lang/Object}}>C{C{Test$Y<S{TY}>}.Q<S{TR}>}}") 487 class R<TR> extends Q<TR> { 488 // no sig 489 class R1 { } 490 491 @Sig(s="<TR2:Ljava/lang/Object;>LTest$Y<TTY;>.R<TTR;>.R1;", 492 t="CS{<TA{TR2:cC{java/lang/Object}}>C{C{C{Test$Y<S{TY}>}.R<S{TR}>}.R1}}") 493 class R2<TR2> extends R1 { } 494 } 495 496 @Sig(s="LTest$Y<TTY;>.Q<TTY;>;", t="C{C{Test$Y<S{TY}>}.Q<S{TY}>}") 497 class S extends Q<TY> { 498 // no sig 499 class S1 { } 500 501 @Sig(s="<TS2:Ljava/lang/Object;>LTest$Y<TTY;>.S.S1;", 502 t="CS{<TA{TS2:cC{java/lang/Object}}>C{C{C{Test$Y<S{TY}>}.S}.S1}}") 503 class S2<TS2> extends S1 { } 504 505 @Sig(s="LTest$Y<TTY;>.S.S2<TTY;>;", 506 t="C{C{C{Test$Y<S{TY}>}.S}.S2<S{TY}>}") 507 class S3 extends S2<TY> { } 508 } 509 } 510} 511 512 513