test/tools/javap/classfile/6888367/T6888367.java

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

mercurial