blob: 91fa9bf0da9961c8cfb7d4a5283b5a4f32c4e196 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2007 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/*
25 * @test
26 * @summary Tests com.sun.beans.TypeResolver
27 * @author Eamonn McManus
28 */
29
30import com.sun.beans.TypeResolver;
31
32import java.lang.reflect.Field;
33import java.lang.reflect.GenericDeclaration;
34import java.lang.reflect.Method;
35import java.lang.reflect.Type;
36import java.lang.reflect.TypeVariable;
37import java.lang.reflect.WildcardType;
38import java.util.ArrayList;
39import java.util.Arrays;
40import java.util.Comparator;
41import java.util.List;
42import java.util.Map;
43
44import sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl;
45import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
46
47public class TestTypeResolver {
48 static final List<Class<?>> failedCases = new ArrayList<Class<?>>();
49
50 public static void main(String[] args) throws Exception {
51 test(TestTypeResolver.class);
52 if (failedCases.isEmpty())
53 System.out.println("TEST PASSED");
54 else {
55 System.out.println("TEST FAILED: failed cases: " + failedCases);
56 throw new Error("TEST FAILED");
57 }
58 }
59
60 private static void test(Class<?> c) throws Exception {
61 /* Every public nested class represents a test. In each case, either
62 * the class contains further nested classes, in which case we
63 * call this method recursively; or it declares or inherits a
64 * method called getThing() and it declares a static field
65 * called "expect" which
66 * is the Type of that method's return value. The test consists
67 * of checking that the value returned by
68 * TypeResolver.resolveInClass is indeed this Type.
69 */
70 System.out.println("Test " + c);
71 Class<?>[] nested = c.getClasses();
72 Arrays.sort(nested, classNameComparator);
73 for (Class<?> n : nested)
74 test(n);
75 final Method m;
76 try {
77 m = c.getMethod("getThing");
78 } catch (NoSuchMethodException e) {
79 if (nested.length == 0) {
80 System.out.println(
81 "TEST ERROR: class " + c.getName() + " has neither " +
82 "nested classes nor getThing() method");
83 failedCases.add(c);
84 }
85 return;
86 }
87 Object expect = null;
88 try {
89 Field f = c.getDeclaredField("expect");
90 expect = f.get(null);
91 } catch (NoSuchFieldException e) {
92 Class<?> outer = c.getDeclaringClass();
93 if (outer != null) {
94 try {
95 Field f = outer.getDeclaredField("expect" + c.getSimpleName());
96 expect = f.get(null);
97 } catch (NoSuchFieldException e1) {
98 }
99 }
100 }
101 if (expect == null) {
102 System.out.println(
103 "TEST ERROR: class " + c.getName() + " has getThing() method " +
104 "but not expect field");
105 failedCases.add(c);
106 return;
107 }
108 Type t = m.getGenericReturnType();
109// t = FixType.fixType(t, c);
110 t = TypeResolver.resolveInClass(c, t);
111 System.out.print("..." + t);
112 // check expected value, and incidentally equals method defined
113 // by private implementations of the various Type interfaces
114 if (expect.equals(t) && t.equals(expect))
115 System.out.println(", as expected");
116 else {
117 System.out.println(" BUT SHOULD BE " + expect);
118 failedCases.add(c);
119 }
120 }
121
122 private static class ClassNameComparator implements Comparator<Class<?>> {
123 public int compare(Class<?> a, Class<?> b) {
124 return a.getName().compareTo(b.getName());
125 }
126 }
127
128 private static final Comparator<Class<?>> classNameComparator =
129 new ClassNameComparator();
130
131 private static abstract class TypeVariableImpl<D extends GenericDeclaration>
132 implements TypeVariable<D> {
133 private final String name;
134 private final D gd;
135 private final Type[] bounds;
136
137 TypeVariableImpl(String name, D gd, Type... bounds) {
138 this.name = name;
139 this.gd = gd;
140 if (bounds.length == 0)
141 bounds = new Type[] {Object.class};
142 this.bounds = bounds.clone();
143 }
144
145 public Type[] getBounds() {
146 return bounds.clone();
147 }
148
149 public D getGenericDeclaration() {
150 return gd;
151 }
152
153 public String getName() {
154 return name;
155 }
156
157 public String toString() {
158 return name;
159 }
160
161 public boolean equals(Object o) {
162 if (!(o instanceof TypeVariable))
163 return false;
164 TypeVariable tv = (TypeVariable) o;
165 return equal(name, tv.getName()) &&
166 equal(gd, tv.getGenericDeclaration()) &&
167 Arrays.equals(bounds, tv.getBounds());
168 }
169
170 public int hashCode() {
171 return hash(name) ^ hash(gd) ^ Arrays.hashCode(bounds);
172 }
173 }
174
175 private static class ClassTypeVariable extends TypeVariableImpl<Class<?>> {
176 ClassTypeVariable(String name, Class<?> gd, Type... bounds) {
177 super(name, gd, bounds);
178 }
179 }
180
181 private static class MethodTypeVariable extends TypeVariableImpl<Method> {
182 MethodTypeVariable(String name, Method gd, Type... bounds) {
183 super(name, gd, bounds);
184 }
185 }
186
187 private static class WildcardTypeImpl implements WildcardType {
188 private final Type[] upperBounds;
189 private final Type[] lowerBounds;
190
191 WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) {
192 if (upperBounds == null || upperBounds.length == 0)
193 upperBounds = new Type[] {Object.class};
194 if (lowerBounds == null)
195 lowerBounds = new Type[0];
196 this.upperBounds = upperBounds.clone();
197 this.lowerBounds = lowerBounds.clone();
198 }
199
200 public Type[] getUpperBounds() {
201 return upperBounds.clone();
202 }
203
204 public Type[] getLowerBounds() {
205 return lowerBounds.clone();
206 }
207
208 public boolean equals(Object o) {
209 if (o instanceof WildcardType) {
210 WildcardType wt = (WildcardType) o;
211 return Arrays.equals(upperBounds, wt.getUpperBounds()) &&
212 Arrays.equals(lowerBounds, wt.getLowerBounds());
213 } else
214 return false;
215 }
216
217 public int hashCode() {
218 return Arrays.hashCode(upperBounds) ^ Arrays.hashCode(lowerBounds);
219 }
220
221 public String toString() {
222 StringBuilder sb = new StringBuilder("?");
223 if (upperBounds.length > 1 || upperBounds[0] != Object.class) {
224 sb.append(" extends");
225 appendBounds(sb, upperBounds);
226 }
227 if (lowerBounds.length > 0) {
228 sb.append(" super");
229 appendBounds(sb, lowerBounds);
230 }
231 return sb.toString();
232 }
233
234 private static void appendBounds(StringBuilder sb, Type[] bounds) {
235 boolean and = false;
236 for (Type bound : bounds) {
237 if (and)
238 sb.append(" &");
239 sb.append(" ");
240 if (bound instanceof Class)
241 sb.append(((Class<?>) bound).getName());
242 else
243 sb.append(bound);
244 and = true;
245 }
246 }
247 }
248
249 static boolean equal(Object x, Object y) {
250 if (x == y)
251 return true;
252 if (x == null || y == null)
253 return false;
254 return x.equals(y);
255 }
256
257 static int hash(Object x) {
258 return (x == null) ? null : x.hashCode();
259 }
260
261
262 public static class Outer<T> {
263 public class Inner {
264 public T getThing() {
265 return null;
266 }
267 }
268
269 static final Type expectInner = new ClassTypeVariable("T", Outer.class);
270 }
271
272 public static class Super<T> {
273 static final Type expect = new ClassTypeVariable("T", Super.class);
274
275 public T getThing() {
276 return null;
277 }
278 }
279
280 public static class Int extends Super<Integer> {
281 static final Type expect = Integer.class;
282 }
283
284 public static class IntOverride extends Int {
285 static final Type expect = Integer.class;
286
287 public Integer getThing() {
288 return null;
289 }
290 }
291
292 public static class Mid<X> extends Super<X> {
293 static final Type expect = new ClassTypeVariable("X", Mid.class);
294 }
295
296 public static class Str extends Mid<String> {
297 static final Type expect = String.class;
298 }
299
300 public static class ListInt extends Super<List<Integer>> {
301 static final Type expect = ParameterizedTypeImpl.make(
302 List.class, new Type[] {Integer.class}, null);
303 }
304
305 public static class ListIntSub extends ListInt {
306 static final Type expect = ParameterizedTypeImpl.make(
307 List.class, new Type[] {Integer.class}, null);
308
309 public List<Integer> getThing() {
310 return null;
311 }
312 }
313
314 public static class ListU<U> extends Super<List<U>> {
315 static final Type expect = ParameterizedTypeImpl.make(
316 List.class, new Type[] {new ClassTypeVariable("U", ListU.class)}, null);
317 }
318
319 public static class ListUInt extends ListU<Integer> {
320 static final Type expect = ParameterizedTypeImpl.make(
321 List.class, new Type[] {Integer.class}, null);
322 }
323
324 public static class ListUSub<V> extends ListU<V> {
325 static final Type expect = ParameterizedTypeImpl.make(
326 List.class, new Type[] {new ClassTypeVariable("V", ListUSub.class)}, null);
327
328 public List<V> getThing() {
329 return null;
330 }
331 }
332
333 public static class ListUSubInt extends ListUSub<Integer> {
334 static final Type expect = ParameterizedTypeImpl.make(
335 List.class, new Type[] {Integer.class}, null);
336 }
337
338 public static class TwoParams<S, T> extends Super<S> {
339 static final Type expect = new ClassTypeVariable("S", TwoParams.class);
340 }
341
342 public static class TwoParamsSub<T> extends TwoParams<T, Integer> {
343 static final Type expect = new ClassTypeVariable("T", TwoParamsSub.class);
344 }
345
346 public static class TwoParamsSubSub extends TwoParamsSub<String> {
347 static final Type expect = String.class;
348 }
349
350 public static interface Intf<T> {
351 static final Type expect = new ClassTypeVariable("T", Intf.class);
352
353 public T getThing();
354 }
355
356 public static abstract class Impl implements Intf<String> {
357 static final Type expect = String.class;
358 }
359
360 public static class Impl2 extends Super<String> implements Intf<String> {
361 static final Type expect = String.class;
362 }
363
364 public static class Bound<T extends Number> extends Super<T> {
365 static final Type expect = new ClassTypeVariable("T", Bound.class, Number.class);
366 }
367
368 public static class BoundInt extends Bound<Integer> {
369 static final Type expect = Integer.class;
370 }
371
372 public static class RawBound extends Bound {
373 static final Type expect = Number.class;
374 }
375
376 public static class RawBoundInt extends BoundInt {
377 static final Type expect = Integer.class;
378 }
379
380 public static class MethodParam<T> {
381 private static final Method m;
382
383 static {
384 try {
385 m = MethodParam.class.getMethod("getThing");
386 } catch (Exception e) {
387 throw new AssertionError(e);
388 }
389 }
390
391 static final Type expect = new MethodTypeVariable("T", m);
392
393 public <T> T getThing() {
394 return null;
395 }
396 }
397
398 public static class Raw extends Super {
399 static final Type expect = Object.class;
400 }
401
402 public static class RawSub extends Raw {
403 static final Type expect = Object.class;
404 }
405
406 public static class SimpleArray extends Super<String[]> {
407 static final Type expect = String[].class;
408 }
409
410 public static class GenericArray extends Super<List<String>[]> {
411 static final Type expect = GenericArrayTypeImpl.make(
412 ParameterizedTypeImpl.make(List.class, new Type[] {String.class}, null));
413 }
414
415 public static class GenericArrayT<T> extends Super<T[]> {
416 static final Type expect = GenericArrayTypeImpl.make(
417 new ClassTypeVariable("T", GenericArrayT.class));
418 }
419
420 public static class GenericArrayTSub extends GenericArrayT<String[]> {
421 static final Type expect = String[][].class;
422 }
423
424 public static class Wildcard extends Super<List<?>> {
425 static final Type expect = ParameterizedTypeImpl.make(
426 List.class, new Type[] {new WildcardTypeImpl(null, null)}, null);
427 }
428
429 public static class WildcardT<T> extends Super<List<? extends T>> {
430 static final Type expect = ParameterizedTypeImpl.make(
431 List.class,
432 new Type[] {
433 new WildcardTypeImpl(
434 new Type[] {new ClassTypeVariable("T", WildcardT.class)},
435 null)},
436 null);
437 }
438
439 public static class WildcardTSub extends WildcardT<Integer> {
440 static final Type expect = ParameterizedTypeImpl.make(
441 List.class,
442 new Type[] {
443 new WildcardTypeImpl(
444 new Type[] {Integer.class},
445 null)},
446 null);
447 }
448
449 public static class WildcardTSubSub<X> extends WildcardTSub {
450 // X is just so we can have a raw subclass
451 static final Type expect = WildcardTSub.expect;
452 }
453
454 public static class RawWildcardTSubSub extends WildcardTSubSub {
455 static final Type expect = List.class;
456 }
457
458 public static class WildcardTSuper<T> extends Super<List<? super T>> {
459 static final Type expect = ParameterizedTypeImpl.make(
460 List.class,
461 new Type[] {
462 new WildcardTypeImpl(
463 null,
464 new Type[] {new ClassTypeVariable("T", WildcardTSuper.class)})},
465 null);
466 }
467
468 public static class WildcardTSuperSub extends WildcardTSuper<Integer> {
469 static final Type expect = ParameterizedTypeImpl.make(
470 List.class,
471 new Type[] {
472 new WildcardTypeImpl(
473 null,
474 new Type[] {Integer.class})},
475 null);
476 }
477
478 public static class SuperMap<K, V> {
479 static final Type expect = ParameterizedTypeImpl.make(
480 Map.class,
481 new Type[] {
482 new ClassTypeVariable("K", SuperMap.class),
483 new ClassTypeVariable("V", SuperMap.class)},
484 null);
485
486 public Map<K, V> getThing() {
487 return null;
488 }
489 }
490
491 public static class SubMap extends SuperMap<String, Integer> {
492 static final Type expect = ParameterizedTypeImpl.make(
493 Map.class,
494 new Type[] {String.class, Integer.class},
495 null);
496 }
497
498 public static class ListListT<T> extends Super<List<List<T>>> {
499 static final Type expect = ParameterizedTypeImpl.make(
500 List.class,
501 new Type[] {
502 ParameterizedTypeImpl.make(
503 List.class,
504 new Type[] {new ClassTypeVariable("T", ListListT.class)},
505 null)},
506 null);
507 }
508
509 public static class ListListString extends ListListT<String> {
510 static final Type expect = ParameterizedTypeImpl.make(
511 List.class,
512 new Type[] {
513 ParameterizedTypeImpl.make(
514 List.class,
515 new Type[] {String.class},
516 null)},
517 null);
518 }
519
520 public static class UExtendsT<T, U extends T> extends Super<U> {
521 static final Type expect = new ClassTypeVariable(
522 "U", UExtendsT.class, new ClassTypeVariable("T", UExtendsT.class));
523 }
524
525 public static class UExtendsTSub extends UExtendsT<Number, Integer> {
526 static final Type expect = Integer.class;
527 }
528
529 public static class SelfRef<T extends SelfRef<T>> extends Super<T> {
530 static final Type expect =
531 SelfRef.class.getTypeParameters()[0];
532 }
533
534 public static class SelfRefSub extends SelfRef<SelfRefSub> {
535 static final Type expect = SelfRefSub.class;
536 }
537}