1/*
2 * Copyright (C) 2007 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.reflect;
18
19import static com.google.common.truth.Truth.assertThat;
20
21import com.google.common.base.Function;
22import com.google.common.collect.ImmutableList;
23import com.google.common.collect.ImmutableMap;
24import com.google.common.collect.ImmutableSet;
25import com.google.common.collect.Maps;
26import com.google.common.primitives.Primitives;
27import com.google.common.testing.EqualsTester;
28import com.google.common.testing.NullPointerTester;
29import com.google.common.testing.SerializableTester;
30import com.google.common.truth.CollectionSubject;
31
32import junit.framework.TestCase;
33
34import java.io.Serializable;
35import java.lang.reflect.Constructor;
36import java.lang.reflect.GenericArrayType;
37import java.lang.reflect.Method;
38import java.lang.reflect.ParameterizedType;
39import java.lang.reflect.Type;
40import java.util.ArrayList;
41import java.util.Collection;
42import java.util.Collections;
43import java.util.List;
44import java.util.Map;
45
46/**
47 * Test cases for {@link TypeToken}.
48 *
49 * @author Sven Mawson
50 * @author Ben Yu
51 */
52public class TypeTokenTest extends TestCase {
53
54  private abstract static class StringList implements List<String> {}
55
56  private abstract static class IntegerList implements List<Integer> {}
57
58  public void testValueEqualityNotInstanceEquality() {
59    TypeToken<List<String>> a = new TypeToken<List<String>>() {};
60    TypeToken<List<String>> b = new TypeToken<List<String>>() {};
61    assertEquals(a, b);
62  }
63
64  public <T> void testVariableTypeTokenNotAllowed() {
65    try {
66      new TypeToken<T>() {};
67      fail();
68    } catch (IllegalStateException expected) {}
69  }
70
71  public void testRawTypeIsCorrect() {
72    TypeToken<List<String>> token = new TypeToken<List<String>>() {};
73    assertEquals(List.class, token.getRawType());
74  }
75
76  public void testTypeIsCorrect() {
77    TypeToken<List<String>> token = new TypeToken<List<String>>() {};
78    assertEquals(StringList.class.getGenericInterfaces()[0], token.getType());
79  }
80
81  @SuppressWarnings("rawtypes") // Trying to test TypeToken.of(List.class)
82  public void testGetClass() {
83    TypeToken<List> token = TypeToken.of(List.class);
84    assertEquals(new TypeToken<List>() {}, token);
85  }
86
87  public void testGetType() {
88    TypeToken<?> t = TypeToken.of(StringList.class.getGenericInterfaces()[0]);
89    assertEquals(new TypeToken<List<String>>() {}, t);
90  }
91
92  public void testNonStaticLocalClass() {
93    class Local<T> {}
94    TypeToken<Local<String>> type = new TypeToken<Local<String>>() {};
95    assertEquals(Types.newParameterizedType(Local.class, String.class),
96        type.getType());
97    assertEquals(new Local<String>() {}.getClass().getGenericSuperclass(), type.getType());
98  }
99
100  public void testStaticLocalClass() {
101    doTestStaticLocalClass();
102  }
103
104  private static void doTestStaticLocalClass() {
105    class Local<T> {}
106    TypeToken<Local<String>> type = new TypeToken<Local<String>>() {};
107    assertEquals(Types.newParameterizedType(Local.class, String.class),
108        type.getType());
109    assertEquals(new Local<String>() {}.getClass().getGenericSuperclass(), type.getType());
110  }
111
112  public void testGenericArrayType() throws Exception {
113    TypeToken<List<String>[]> token = new TypeToken<List<String>[]>() {};
114    assertEquals(List[].class, token.getRawType());
115    assertTrue(token.getType() instanceof GenericArrayType);
116  }
117
118  public void testMultiDimensionalGenericArrayType() throws Exception {
119    TypeToken<List<Long>[][][]> token = new TypeToken<List<Long>[][][]>() {};
120    assertEquals(List[][][].class, token.getRawType());
121    assertTrue(token.getType() instanceof GenericArrayType);
122  }
123
124  public <T> void testGenericVariableTypeArrays() throws Exception {
125    assertEquals("T[]", new TypeToken<T[]>() {}.toString());
126  }
127
128  public void testResolveType() throws Exception {
129    Method getFromList = List.class.getMethod("get", int.class);
130    TypeToken<?> returnType = new TypeToken<List<String>>() {}
131        .resolveType(getFromList.getGenericReturnType());
132    assertEquals(String.class, returnType.getType());
133  }
134
135  public <F extends Enum<F> & Function<String, Integer> & Iterable<Long>>
136  void testResolveType_fromTypeVariable() throws Exception {
137    TypeToken<?> f = TypeToken.of(new TypeCapture<F>() {}.capture());
138    assertEquals(String.class,
139        f.resolveType(Function.class.getTypeParameters()[0]).getType());
140    assertEquals(Integer.class,
141        f.resolveType(Function.class.getTypeParameters()[1]).getType());
142    assertEquals(Long.class,
143        f.resolveType(Iterable.class.getTypeParameters()[0]).getType());
144  }
145
146  public <E extends Comparable<Iterable<String>> & Iterable<Integer>>
147  void testResolveType_fromTypeVariable_onlyDirectBoundsAreUsed() throws Exception {
148    TypeToken<?> e = TypeToken.of(new TypeCapture<E>() {}.capture());
149    assertEquals(Integer.class,
150        e.resolveType(Iterable.class.getTypeParameters()[0]).getType());
151  }
152
153  public void testResolveType_fromWildcard() throws Exception {
154    ParameterizedType withWildcardType = (ParameterizedType)
155        new TypeCapture<Comparable<? extends Iterable<String>>>() {}.capture();
156    TypeToken<?> wildcardType = TypeToken.of(withWildcardType.getActualTypeArguments()[0]);
157    assertEquals(String.class,
158        wildcardType.resolveType(Iterable.class.getTypeParameters()[0]).getType());
159  }
160
161  public void testGetTypes_noSuperclass() {
162    TypeToken<Object>.TypeSet types = new TypeToken<Object>() {}.getTypes();
163    assertThat(types).has().item(TypeToken.of(Object.class));
164    assertThat(types.rawTypes()).has().item(Object.class);
165    assertThat(types.interfaces()).isEmpty();
166    assertThat(types.interfaces().rawTypes()).isEmpty();
167    assertThat(types.classes()).has().item(TypeToken.of(Object.class));
168    assertThat(types.classes().rawTypes()).has().item(Object.class);
169  }
170
171  public void testGetTypes_fromInterface() {
172    TypeToken<Interface1>.TypeSet types = new TypeToken<Interface1>() {}.getTypes();
173    assertThat(types).has().item(TypeToken.of(Interface1.class));
174    assertThat(types.rawTypes()).has().item(Interface1.class);
175    assertThat(types.interfaces()).has().item(TypeToken.of(Interface1.class));
176    assertThat(types.interfaces().rawTypes()).has().item(Interface1.class);
177    assertThat(types.classes()).isEmpty();
178    assertThat(types.classes().rawTypes()).isEmpty();
179  }
180
181  public void testGetTypes_fromPrimitive() {
182    TypeToken<Integer>.TypeSet types = TypeToken.of(int.class).getTypes();
183    assertThat(types).has().item(TypeToken.of(int.class));
184    assertThat(types.rawTypes()).has().item(int.class);
185    assertThat(types.interfaces()).isEmpty();
186    assertThat(types.interfaces().rawTypes()).isEmpty();
187    assertThat(types.classes()).has().item(TypeToken.of(int.class));
188    assertThat(types.classes().rawTypes()).has().item(int.class);
189  }
190
191  public void testGetTypes_withInterfacesAndSuperclasses() {
192    abstract class Class2 extends Class1 implements Interface12 {}
193    abstract class Class3<T> extends Class2 implements Interface3<T> {}
194    TypeToken<Class3<String>>.TypeSet types = new TypeToken<Class3<String>>() {}.getTypes();
195    makeUnmodifiable(types).has().exactly(
196        new TypeToken<Class3<String>>() {},
197        new TypeToken<Interface3<String>>() {},
198        new TypeToken<Iterable<String>>() {},
199        TypeToken.of(Class2.class),
200        TypeToken.of(Interface12.class),
201        TypeToken.of(Interface1.class),
202        TypeToken.of(Interface2.class),
203        TypeToken.of(Class1.class),
204        TypeToken.of(Object.class));
205    makeUnmodifiable(types.interfaces()).has().exactly(
206        new TypeToken<Interface3<String>>() {},
207        TypeToken.of(Interface12.class),
208        TypeToken.of(Interface1.class),
209        TypeToken.of(Interface2.class),
210        new TypeToken<Iterable<String>>() {});
211    makeUnmodifiable(types.classes()).has().exactly(
212        new TypeToken<Class3<String>>() {},
213        TypeToken.of(Class2.class),
214        TypeToken.of(Class1.class),
215        TypeToken.of(Object.class));
216    assertSubtypeFirst(types);
217  }
218
219  public void testGetTypes_rawTypes_withInterfacesAndSuperclasses() {
220    abstract class Class2 extends Class1 implements Interface12 {}
221    abstract class Class3<T> extends Class2 implements Interface3<T> {}
222    TypeToken<Class3<String>>.TypeSet types = new TypeToken<Class3<String>>() {}.getTypes();
223    makeUnmodifiable(types.rawTypes()).has().exactly(
224        Class3.class, Interface3.class,
225        Iterable.class,
226        Class2.class,
227        Interface12.class,
228        Interface1.class,
229        Interface2.class,
230        Class1.class,
231        Object.class);
232    makeUnmodifiable(types.interfaces().rawTypes()).has().exactly(
233        Interface3.class,
234        Interface12.class,
235        Interface1.class,
236        Interface2.class,
237        Iterable.class);
238    makeUnmodifiable(types.classes().rawTypes()).has().exactly(
239        Class3.class,
240        Class2.class,
241        Class1.class,
242        Object.class);
243    assertSubtypeFirst(types);
244  }
245
246  public <A extends Class1 & Interface1, B extends A>
247  void testGetTypes_ignoresTypeVariablesByDefault() {
248    TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes();
249    makeUnmodifiable(types).has().exactly(
250        TypeToken.of(Interface1.class), TypeToken.of(Class1.class),
251        TypeToken.of(Object.class));
252    assertSubtypeFirst(types);
253    makeUnmodifiable(types.interfaces())
254        .has().exactly(TypeToken.of(Interface1.class))
255        .inOrder();
256    makeUnmodifiable(types.classes())
257        .has().exactly(TypeToken.of(Class1.class), TypeToken.of(Object.class))
258        .inOrder();
259  }
260
261  public <A extends Class1 & Interface1, B extends A>
262  void testGetTypes_rawTypes_ignoresTypeVariablesByDefault() {
263    TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes();
264    makeUnmodifiable(types.rawTypes())
265        .has().exactly(Interface1.class, Class1.class, Object.class);
266    makeUnmodifiable(types.interfaces().rawTypes())
267        .has().exactly(Interface1.class)
268        .inOrder();
269    makeUnmodifiable(types.classes().rawTypes())
270        .has().exactly(Class1.class, Object.class)
271        .inOrder();
272  }
273
274  public <A extends Interface1 & Interface2 & Interface3<String>>
275  void testGetTypes_manyBounds() {
276    TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<A>() {}.capture()).getTypes();
277    makeUnmodifiable(types.rawTypes())
278        .has().exactly(Interface1.class, Interface2.class, Interface3.class, Iterable.class);
279  }
280
281  private static void assertSubtypeFirst(TypeToken<?>.TypeSet types) {
282    assertSubtypeTokenBeforeSupertypeToken(types);
283    assertSubtypeTokenBeforeSupertypeToken(types.interfaces());
284    assertSubtypeTokenBeforeSupertypeToken(types.classes());
285    assertSubtypeBeforeSupertype(types.rawTypes());
286    assertSubtypeBeforeSupertype(types.interfaces().rawTypes());
287    assertSubtypeBeforeSupertype(types.classes().rawTypes());
288  }
289
290  private static void assertSubtypeTokenBeforeSupertypeToken(
291      Iterable<? extends TypeToken<?>> types) {
292    int i = 0;
293    for (TypeToken<?> left : types) {
294      int j = 0;
295      for (TypeToken<?> right : types) {
296        if (left.isAssignableFrom(right)) {
297          assertTrue(left + " should be after " + right, i >= j);
298        }
299        j++;
300      }
301      i++;
302    }
303  }
304
305  private static void assertSubtypeBeforeSupertype(Iterable<? extends Class<?>> types) {
306    int i = 0;
307    for (Class<?> left : types) {
308      int j = 0;
309      for (Class<?> right : types) {
310        if (left.isAssignableFrom(right)) {
311          assertTrue(left + " should be after " + right, i >= j);
312        }
313        j++;
314      }
315      i++;
316    }
317  }
318
319  // Tests to make sure assertSubtypeBeforeSupertype() works.
320
321  public void testAssertSubtypeTokenBeforeSupertypeToken_empty() {
322    assertSubtypeTokenBeforeSupertypeToken(ImmutableList.<TypeToken<?>>of());
323  }
324
325  public void testAssertSubtypeTokenBeforeSupertypeToken_oneType() {
326    assertSubtypeTokenBeforeSupertypeToken(ImmutableList.of(TypeToken.of(String.class)));
327  }
328
329  public void testAssertSubtypeTokenBeforeSupertypeToken_subtypeFirst() {
330    assertSubtypeTokenBeforeSupertypeToken(
331        ImmutableList.of(TypeToken.of(String.class), TypeToken.of(CharSequence.class)));
332  }
333
334  public void testAssertSubtypeTokenBeforeSupertypeToken_supertypeFirst() {
335    try {
336      assertSubtypeTokenBeforeSupertypeToken(
337          ImmutableList.of(TypeToken.of(CharSequence.class), TypeToken.of(String.class)));
338    } catch (AssertionError expected) {
339      return;
340    }
341    fail();
342  }
343
344  public void testAssertSubtypeTokenBeforeSupertypeToken_duplicate() {
345    try {
346      assertSubtypeTokenBeforeSupertypeToken(
347          ImmutableList.of(TypeToken.of(String.class), TypeToken.of(String.class)));
348    } catch (AssertionError expected) {
349      return;
350    }
351    fail();
352  }
353
354  public void testAssertSubtypeBeforeSupertype_empty() {
355    assertSubtypeBeforeSupertype(ImmutableList.<Class<?>>of());
356  }
357
358  public void testAssertSubtypeBeforeSupertype_oneType() {
359    assertSubtypeBeforeSupertype(ImmutableList.of(String.class));
360  }
361
362  public void testAssertSubtypeBeforeSupertype_subtypeFirst() {
363    assertSubtypeBeforeSupertype(
364        ImmutableList.of(String.class, CharSequence.class));
365  }
366
367  public void testAssertSubtypeBeforeSupertype_supertypeFirst() {
368    try {
369      assertSubtypeBeforeSupertype(
370          ImmutableList.of(CharSequence.class, String.class));
371    } catch (AssertionError expected) {
372      return;
373    }
374    fail();
375  }
376
377  public void testAssertSubtypeBeforeSupertype_duplicate() {
378    try {
379      assertSubtypeBeforeSupertype(
380          ImmutableList.of(String.class, String.class));
381    } catch (AssertionError expected) {
382      return;
383    }
384    fail();
385  }
386
387  public void testGetGenericSuperclass_noSuperclass() {
388    assertNull(new TypeToken<Object>() {}.getGenericSuperclass());
389    assertEquals(TypeToken.of(Object.class),
390        new TypeToken<Object[]>() {}.getGenericSuperclass());
391    assertNull(new TypeToken<List<String>>() {}.getGenericSuperclass());
392    assertEquals(TypeToken.of(Object.class),
393        new TypeToken<List<String>[]>() {}.getGenericSuperclass());
394  }
395
396  public void testGetGenericSuperclass_withSuperclass() {
397    TypeToken<? super ArrayList<String>> superToken =
398        new TypeToken<ArrayList<String>>() {}.getGenericSuperclass();
399    assertEquals(ArrayList.class.getSuperclass(), superToken.getRawType());
400    assertEquals(String.class,
401        ((ParameterizedType) superToken.getType()).getActualTypeArguments()[0]);
402    assertEquals(TypeToken.of(Base.class), TypeToken.of(Sub.class).getGenericSuperclass());
403    assertEquals(TypeToken.of(Object.class), TypeToken.of(Sub[].class).getGenericSuperclass());
404  }
405
406  public <T> void testGetGenericSuperclass_typeVariable_unbounded() {
407    assertEquals(TypeToken.of(Object.class),
408        TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericSuperclass());
409    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
410  }
411
412  public <T extends ArrayList<String> & CharSequence>
413  void testGetGenericSuperclass_typeVariable_boundIsClass() {
414    assertEquals(new TypeToken<ArrayList<String>>() {},
415        TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericSuperclass());
416    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
417  }
418
419  public <T extends Enum<T> & CharSequence>
420  void testGetGenericSuperclass_typeVariable_boundIsFBoundedClass() {
421    assertEquals(new TypeToken<Enum<T>>() {},
422        TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericSuperclass());
423    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
424  }
425
426  public <T extends List<String> & CharSequence>
427  void testGetGenericSuperclass_typeVariable_boundIsInterface() {
428    assertNull(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericSuperclass());
429    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
430  }
431
432  public <T extends ArrayList<String> & CharSequence, T1 extends T>
433  void testGetGenericSuperclass_typeVariable_boundIsTypeVariableAndClass() {
434    assertEquals(TypeToken.of(new TypeCapture<T>() {}.capture()),
435        TypeToken.of(new TypeCapture<T1>() {}.capture()).getGenericSuperclass());
436    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
437  }
438
439  public <T extends List<String> & CharSequence, T1 extends T>
440  void testGetGenericSuperclass_typeVariable_boundIsTypeVariableAndInterface() {
441    assertNull(TypeToken.of(new TypeCapture<T1>() {}.capture()).getGenericSuperclass());
442    assertEquals(TypeToken.of(Object.class), new TypeToken<T1[]>() {}.getGenericSuperclass());
443  }
444
445  public void testGetGenericSuperclass_wildcard_lowerBounded() {
446    assertEquals(TypeToken.of(Object.class),
447        TypeToken.of(Types.supertypeOf(String.class)).getGenericSuperclass());
448    assertEquals(new TypeToken<Object>() {},
449        TypeToken.of(Types.supertypeOf(String[].class)).getGenericSuperclass());
450    assertEquals(new TypeToken<Object>() {},
451        TypeToken.of(Types.supertypeOf(CharSequence.class)).getGenericSuperclass());
452  }
453
454  public void testGetGenericSuperclass_wildcard_boundIsClass() {
455    assertEquals(TypeToken.of(Object.class),
456        TypeToken.of(Types.subtypeOf(Object.class)).getGenericSuperclass());
457    assertEquals(new TypeToken<Object[]>() {},
458        TypeToken.of(Types.subtypeOf(Object[].class)).getGenericSuperclass());
459  }
460
461  public void testGetGenericSuperclass_wildcard_boundIsInterface() {
462    assertNull(TypeToken.of(Types.subtypeOf(CharSequence.class)).getGenericSuperclass());
463    assertEquals(new TypeToken<CharSequence[]>() {},
464        TypeToken.of(Types.subtypeOf(CharSequence[].class)).getGenericSuperclass());
465  }
466
467  public <T> void testGetGenericInterfaces_typeVariable_unbounded() {
468    assertThat(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces()).isEmpty();
469    assertHasArrayInterfaces(new TypeToken<T[]>() {});
470  }
471
472  public <T extends NoInterface> void testGetGenericInterfaces_typeVariable_boundIsClass() {
473    assertThat(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces()).isEmpty();
474    assertHasArrayInterfaces(new TypeToken<T[]>() {});
475  }
476
477  public <T extends NoInterface&Iterable<String>>
478  void testGetGenericInterfaces_typeVariable_boundsAreClassWithInterface() {
479    makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
480        .has().exactly(new TypeToken<Iterable<String>>() {});
481    assertHasArrayInterfaces(new TypeToken<T[]>() {});
482  }
483
484  public <T extends CharSequence&Iterable<String>>
485  void testGetGenericInterfaces_typeVariable_boundsAreInterfaces() {
486    makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
487        .has().exactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<String>>() {});
488    assertHasArrayInterfaces(new TypeToken<T[]>() {});
489  }
490
491  public <T extends CharSequence&Iterable<T>>
492  void testGetGenericInterfaces_typeVariable_boundsAreFBoundedInterfaces() {
493    makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
494        .has().exactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<T>>() {});
495    assertHasArrayInterfaces(new TypeToken<T[]>() {});
496  }
497
498  public <T extends Base&Iterable<T>>
499  void testGetGenericInterfaces_typeVariable_boundsAreClassWithFBoundedInterface() {
500    makeUnmodifiable(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
501        .has().exactly(new TypeToken<Iterable<T>>() {});
502    assertHasArrayInterfaces(new TypeToken<T[]>() {});
503  }
504
505  public <T extends NoInterface, T1 extends T, T2 extends T1>
506  void testGetGenericInterfaces_typeVariable_boundIsTypeVariableAndClass() {
507    assertThat(TypeToken.of(new TypeCapture<T2>() {}.capture()).getGenericInterfaces()).isEmpty();
508    assertHasArrayInterfaces(new TypeToken<T2[]>() {});
509  }
510
511  public <T extends Iterable<T>, T1 extends T, T2 extends T1>
512  void testGetGenericInterfaces_typeVariable_boundIsTypeVariableAndInterface() {
513    makeUnmodifiable(TypeToken.of(new TypeCapture<T2>() {}.capture()).getGenericInterfaces())
514        .has().exactly(TypeToken.of(new TypeCapture<T1>() {}.capture()));
515    assertHasArrayInterfaces(new TypeToken<T2[]>() {});
516  }
517
518  public void testGetGenericInterfaces_wildcard_lowerBounded() {
519    assertThat(TypeToken.of(Types.supertypeOf(String.class)).getGenericInterfaces()).isEmpty();
520    assertThat(TypeToken.of(Types.supertypeOf(String[].class)).getGenericInterfaces()).isEmpty();
521  }
522
523  public void testGetGenericInterfaces_wildcard_boundIsClass() {
524    assertThat(TypeToken.of(Types.subtypeOf(Object.class)).getGenericInterfaces()).isEmpty();
525    assertThat(TypeToken.of(Types.subtypeOf(Object[].class)).getGenericInterfaces()).isEmpty();
526  }
527
528  public void testGetGenericInterfaces_wildcard_boundIsInterface() {
529    TypeToken<Iterable<String>> interfaceType = new TypeToken<Iterable<String>>() {};
530    makeUnmodifiable(TypeToken.of(Types.subtypeOf(interfaceType.getType())).getGenericInterfaces())
531        .has().exactly(interfaceType);
532    assertHasArrayInterfaces(new TypeToken<Iterable<String>[]>() {});
533  }
534
535  public void testGetGenericInterfaces_noInterface() {
536    assertThat(new TypeToken<NoInterface>() {}.getGenericInterfaces()).isEmpty();
537    assertHasArrayInterfaces(new TypeToken<NoInterface[]>() {});
538  }
539
540  public void testGetGenericInterfaces_withInterfaces() {
541    Map<Class<?>, Type> interfaceMap = Maps.newHashMap();
542    for (TypeToken<?> interfaceType:
543        new TypeToken<Implementation<Integer, String>>() {}.getGenericInterfaces()) {
544      interfaceMap.put(interfaceType.getRawType(), interfaceType.getType());
545    }
546    assertEquals(ImmutableMap.of(
547            Iterable.class, new TypeToken<Iterable<String>>() {}.getType(),
548            Map.class, new TypeToken<Map<Integer, String>>() {}.getType()),
549        interfaceMap);
550  }
551
552  private interface Interface1 {}
553  private interface Interface2 {}
554  private interface Interface3<T> extends Iterable<T> {}
555  private interface Interface12 extends Interface1, Interface2 {}
556  private static class Class1 implements Interface1 {}
557
558  private static final class NoInterface {}
559
560  private abstract static class Implementation<K, V>
561      implements Iterable<V>, Map<K, V> {}
562
563  private abstract static class First<T> {}
564
565  private abstract static class Second<D> extends First<D> {}
566
567  private abstract static class Third<T, D> extends Second<T> {}
568
569  private abstract static class Fourth<T, D> extends Third<D, T> {}
570
571  private static class ConcreteIS extends Fourth<Integer, String> {}
572
573  private static class ConcreteSI extends Fourth<String, Integer> {}
574
575  public void testAssignableClassToClass() {
576    @SuppressWarnings("rawtypes") // To test TypeToken<List>
577    TypeToken<List> tokL = new TypeToken<List>() {};
578    assertTrue(tokL.isAssignableFrom(List.class));
579    assertTrue(tokL.isAssignableFrom(ArrayList.class));
580    assertFalse(tokL.isAssignableFrom(List[].class));
581
582    TypeToken<Number> tokN = new TypeToken<Number>() {};
583    assertTrue(tokN.isAssignableFrom(Number.class));
584    assertTrue(tokN.isAssignableFrom(Integer.class));
585  }
586
587  public <T> void testAssignableParameterizedTypeToObject() {
588    assertTrue(TypeToken.of(Object.class).isAssignableFrom(
589        TypeToken.of(new TypeCapture<T>() {}.capture())));
590    assertFalse(TypeToken.of(int.class).isAssignableFrom(
591        TypeToken.of(new TypeCapture<T>() {}.capture())));
592  }
593
594  public <T, T1 extends T> void testAssignableGenericArrayToGenericArray() {
595    assertTrue(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T[]>() {}));
596    assertTrue(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T1[]>() {}));
597    assertFalse(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T[][]>() {}));
598  }
599
600  public void testAssignableWildcardBoundedByArrayToArrayClass() throws Exception {
601    Type wildcardType = Types.subtypeOf(Object[].class);
602    assertTrue(TypeToken.of(Object[].class).isAssignableFrom(wildcardType));
603    assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType));
604    assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType));
605    assertFalse(TypeToken.of(int[].class).isAssignableFrom(wildcardType));
606  }
607
608  public void testAssignableArrayClassToBoundedWildcard() throws Exception {
609    TypeToken<?> upperBounded = TypeToken.of(Types.subtypeOf(Object[].class));
610    TypeToken<?> lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class));
611    assertTrue(upperBounded.isAssignableFrom(Object[].class));
612    assertTrue(upperBounded.isAssignableFrom(Object[][].class));
613    assertTrue(upperBounded.isAssignableFrom(String[].class));
614    assertTrue(lowerBounded.isAssignableFrom(Object[].class));
615    assertTrue(lowerBounded.isAssignableFrom(Object.class));
616    assertFalse(lowerBounded.isAssignableFrom(Object[][].class));
617    assertFalse(lowerBounded.isAssignableFrom(String[].class));
618  }
619
620  public void testAssignableWildcardBoundedByIntArrayToArrayClass() throws Exception {
621    Type wildcardType = Types.subtypeOf(int[].class);
622    assertTrue(TypeToken.of(int[].class).isAssignableFrom(wildcardType));
623    assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType));
624    assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType));
625    assertFalse(TypeToken.of(Object[].class).isAssignableFrom(wildcardType));
626  }
627
628  public void testAssignableWildcardToWildcard() throws Exception {
629    TypeToken<?> upperBounded = TypeToken.of(Types.subtypeOf(Object[].class));
630    TypeToken<?> lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class));
631    assertFalse(lowerBounded.isAssignableFrom(upperBounded));
632    assertTrue(lowerBounded.isAssignableFrom(lowerBounded));
633    assertTrue(upperBounded.isAssignableFrom(upperBounded));
634    assertFalse(upperBounded.isAssignableFrom(lowerBounded));
635  }
636
637  public <T> void testAssignableGenericArrayToArrayClass() {
638    assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken<T[]>() {}));
639    assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken<T[][]>() {}));
640    assertTrue(TypeToken.of(Object[][].class).isAssignableFrom(new TypeToken<T[][]>() {}));
641  }
642
643  public void testAssignableParameterizedTypeToClass() {
644    @SuppressWarnings("rawtypes") // Trying to test raw class
645    TypeToken<List> tokL = new TypeToken<List>() {};
646    assertTrue(tokL.isAssignableFrom(StringList.class));
647    assertTrue(tokL.isAssignableFrom(
648        StringList.class.getGenericInterfaces()[0]));
649
650    @SuppressWarnings("rawtypes") // Trying to test raw class
651    TypeToken<Second> tokS = new TypeToken<Second>() {};
652    assertTrue(tokS.isAssignableFrom(Second.class));
653    assertTrue(tokS.isAssignableFrom(Third.class.getGenericSuperclass()));
654  }
655
656  public void testAssignableArrayToClass() throws Exception {
657    @SuppressWarnings("rawtypes") // Trying to test raw class
658    TypeToken<List[]> tokL = new TypeToken<List[]>() {};
659    assertTrue(tokL.isAssignableFrom(List[].class));
660    assertFalse(tokL.isAssignableFrom(List.class));
661
662    @SuppressWarnings("rawtypes") // Trying to test raw class
663    TypeToken<Second[]> tokS = new TypeToken<Second[]>() {};
664    assertTrue(tokS.isAssignableFrom(Second[].class));
665    assertTrue(tokS.isAssignableFrom(Third[].class));
666  }
667
668  @SuppressWarnings("rawtypes") // Trying to test raw class
669  public void testAssignableTokenToClass() {
670    TypeToken<List> tokL = new TypeToken<List>() {};
671    assertTrue(tokL.isAssignableFrom(new TypeToken<List>() {}));
672    assertTrue(tokL.isAssignableFrom(new TypeToken<List<String>>() {}));
673    assertTrue(tokL.isAssignableFrom(new TypeToken<List<?>>() {}));
674
675    TypeToken<Second> tokS = new TypeToken<Second>() {};
676    assertTrue(tokS.isAssignableFrom(new TypeToken<Second>() {}));
677    assertTrue(tokS.isAssignableFrom(new TypeToken<Third>() {}));
678    assertTrue(tokS.isAssignableFrom(
679        new TypeToken<Third<String, Integer>>() {}));
680
681    TypeToken<List[]> tokA = new TypeToken<List[]>() {};
682    assertTrue(tokA.isAssignableFrom(new TypeToken<List[]>() {}));
683    assertTrue(tokA.isAssignableFrom(new TypeToken<List<String>[]>() {}));
684    assertTrue(tokA.isAssignableFrom(new TypeToken<List<?>[]>() {}));
685  }
686
687  public void testAssignableClassToType() {
688    TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
689    assertTrue(tokenL.isAssignableFrom(StringList.class));
690    assertFalse(tokenL.isAssignableFrom(List.class));
691
692    TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
693    assertTrue(tokenF.isAssignableFrom(ConcreteIS.class));
694    assertFalse(tokenF.isAssignableFrom(ConcreteSI.class));
695  }
696
697  public void testAssignableClassToArrayType() {
698    TypeToken<List<String>[]> tokenL = new TypeToken<List<String>[]>() {};
699    assertTrue(tokenL.isAssignableFrom(StringList[].class));
700    assertFalse(tokenL.isAssignableFrom(List[].class));
701  }
702
703  public void testAssignableParameterizedTypeToType() {
704    TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
705    assertTrue(tokenL.isAssignableFrom(
706        StringList.class.getGenericInterfaces()[0]));
707    assertFalse(tokenL.isAssignableFrom(
708        IntegerList.class.getGenericInterfaces()[0]));
709
710    TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
711    assertTrue(tokenF.isAssignableFrom(
712        ConcreteIS.class.getGenericSuperclass()));
713    assertFalse(tokenF.isAssignableFrom(
714        ConcreteSI.class.getGenericSuperclass()));
715  }
716
717  public void testGenericArrayTypeToArrayType() throws Exception {
718    TypeToken<List<String>[]> tokL = new TypeToken<List<String>[]>() {};
719    TypeToken<ArrayList<String>[]> token =
720        new TypeToken<ArrayList<String>[]>() {};
721    assertTrue(tokL.isAssignableFrom(tokL.getType()));
722    assertTrue(tokL.isAssignableFrom(token.getType()));
723  }
724
725  public void testAssignableTokenToType() {
726    TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
727    assertTrue(tokenL.isAssignableFrom(new TypeToken<List<String>>() {}));
728    assertTrue(tokenL.isAssignableFrom(new TypeToken<ArrayList<String>>() {}));
729    assertTrue(tokenL.isAssignableFrom(new TypeToken<StringList>() {}));
730
731    TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
732    assertTrue(tokenF.isAssignableFrom(new TypeToken<Second<String>>() {}));
733    assertTrue(tokenF.isAssignableFrom(
734        new TypeToken<Third<String, Integer>>() {}));
735    assertFalse(tokenF.isAssignableFrom(
736        new TypeToken<Third<Integer, String>>() {}));
737    assertTrue(tokenF.isAssignableFrom(
738        new TypeToken<Fourth<Integer, String>>() {}));
739    assertFalse(tokenF.isAssignableFrom(
740        new TypeToken<Fourth<String, Integer>>() {}));
741    assertTrue(tokenF.isAssignableFrom(new TypeToken<ConcreteIS>() {}));
742    assertFalse(tokenF.isAssignableFrom(new TypeToken<ConcreteSI>() {}));
743  }
744
745  public void testAssignableWithWildcards() {
746    TypeToken<?> unboundedToken = new TypeToken<List<?>>() {};
747    TypeToken<?> upperBoundToken = new TypeToken<List<? extends Number>>() {};
748    TypeToken<?> lowerBoundToken = new TypeToken<List<? super Number>>() {};
749    TypeToken<?> concreteToken = new TypeToken<List<Number>>() {};
750    TypeToken<?> subtypeToken = new TypeToken<List<Integer>>() {};
751    TypeToken<?> supertypeToken = new TypeToken<List<Serializable>>() {};
752    List<TypeToken<?>> allTokens = ImmutableList.of(
753        unboundedToken, upperBoundToken, lowerBoundToken,
754        concreteToken, subtypeToken, supertypeToken);
755
756    for (TypeToken<?> typeToken : allTokens) {
757      assertTrue(typeToken.toString(), unboundedToken.isAssignableFrom(typeToken));
758    }
759
760    assertFalse(upperBoundToken.isAssignableFrom(unboundedToken));
761    assertTrue(upperBoundToken.isAssignableFrom(upperBoundToken));
762    assertFalse(upperBoundToken.isAssignableFrom(lowerBoundToken));
763    assertTrue(upperBoundToken.isAssignableFrom(concreteToken));
764    assertTrue(upperBoundToken.isAssignableFrom(subtypeToken));
765    assertFalse(upperBoundToken.isAssignableFrom(supertypeToken));
766
767    assertFalse(lowerBoundToken.isAssignableFrom(unboundedToken));
768    assertFalse(lowerBoundToken.isAssignableFrom(upperBoundToken));
769    assertTrue(lowerBoundToken.isAssignableFrom(lowerBoundToken));
770    assertTrue(lowerBoundToken.isAssignableFrom(concreteToken));
771    assertFalse(lowerBoundToken.isAssignableFrom(subtypeToken));
772    assertTrue(lowerBoundToken.isAssignableFrom(supertypeToken));
773
774    for (TypeToken<?> typeToken : allTokens) {
775      assertEquals(typeToken.toString(),
776          typeToken == concreteToken, concreteToken.isAssignableFrom(typeToken));
777    }
778
779    for (TypeToken<?> typeToken : allTokens) {
780      assertEquals(typeToken.toString(),
781          typeToken == subtypeToken, subtypeToken.isAssignableFrom(typeToken));
782    }
783
784    for (TypeToken<?> typeToken : allTokens) {
785      assertEquals(typeToken.toString(),
786          typeToken == supertypeToken, supertypeToken.isAssignableFrom(typeToken));
787    }
788  }
789
790  public <N1 extends Number, N2 extends Number, N11 extends N1>
791      void testIsAssignableFrom_typeVariable() {
792    assertAssignable(TypeToken.of(new TypeCapture<N1>() {}.capture()),
793        TypeToken.of(new TypeCapture<N1>() {}.capture()));
794    assertNotAssignable(new TypeToken<List<N11>>() {},
795        new TypeToken<List<N1>>() {});
796    assertNotAssignable(new TypeToken<Number>() {},
797        TypeToken.of(new TypeCapture<N1>() {}.capture()));
798    assertAssignable(TypeToken.of(new TypeCapture<N11>() {}.capture()),
799        TypeToken.of(new TypeCapture<N1>() {}.capture()));
800    assertNotAssignable(TypeToken.of(new TypeCapture<N2>() {}.capture()),
801        TypeToken.of(new TypeCapture<N1>() {}.capture()));
802  }
803
804  public <N1 extends Number, N2 extends Number, N11 extends N1>
805      void testIsAssignableFrom_equalWildcardTypes() {
806    assertAssignable(new TypeToken<List<? extends N1>>() {},
807        new TypeToken<List<? extends N1>>() {});
808    assertAssignable(new TypeToken<List<? super N1>>() {},
809        new TypeToken<List<? super N1>>() {});
810    assertAssignable(new TypeToken<List<? extends Number>>() {},
811        new TypeToken<List<? extends Number>>() {});
812    assertAssignable(new TypeToken<List<? super Number>>() {},
813        new TypeToken<List<? super Number>>() {});
814  }
815
816  public <N> void testIsAssignableFrom_wildcard_noBound() {
817    assertAssignable(new TypeToken<List<? super N>>() {},
818        new TypeToken<List<?>>() {});
819    assertAssignable(new TypeToken<List<N>>() {},
820        new TypeToken<List<?>>() {});
821  }
822
823  public <N1 extends Number, N2 extends Number, N11 extends N1>
824      void testIsAssignableFrom_wildcardType_upperBoundMatch() {
825    // ? extends T
826    assertAssignable(new TypeToken<List<N11>>() {},
827        new TypeToken<List<? extends N1>>() {});
828    assertNotAssignable(new TypeToken<List<N1>>() {},
829        new TypeToken<List<? extends N11>>() {});
830    assertNotAssignable(new TypeToken<List<Number>>() {},
831        new TypeToken<List<? extends N11>>() {});
832
833    // ? extends Number
834    assertAssignable(new TypeToken<List<N1>>() {},
835        new TypeToken<List<? extends Number>>() {});
836    assertAssignable(new TypeToken<ArrayList<N1>>() {},
837        new TypeToken<List<? extends Number>>() {});
838    assertAssignable(new TypeToken<List<? extends N11>>() {},
839        new TypeToken<List<? extends Number>>() {});
840  }
841
842  public <N1 extends Number, N2 extends Number, N11 extends N1>
843      void testIsAssignableFrom_wildcardType_lowerBoundMatch() {
844    // ? super T
845    assertAssignable(new TypeToken<List<N1>>() {},
846        new TypeToken<List<? super N11>>() {});
847    assertAssignable(new TypeToken<ArrayList<Number>>() {},
848        new TypeToken<List<? super N1>>() {});
849    assertNotAssignable(new TypeToken<ArrayList<? super N11>>() {},
850        new TypeToken<List<? super Number>>() {});
851    assertAssignable(new TypeToken<ArrayList<? super N1>>() {},
852        new TypeToken<List<? super N11>>() {});
853    assertAssignable(new TypeToken<ArrayList<? super Number>>() {},
854        new TypeToken<List<? super N11>>() {});
855
856    // ? super Number
857    assertNotAssignable(new TypeToken<ArrayList<N11>>() {},
858        new TypeToken<List<? super Number>>() {});
859    assertAssignable(new TypeToken<ArrayList<Number>>() {},
860        new TypeToken<List<? super Number>>() {});
861    assertAssignable(new TypeToken<ArrayList<Object>>() {},
862        new TypeToken<List<? super Number>>() {});
863  }
864
865  public <L extends List<R>, R extends List<L>>
866      void testIsAssignableFrom_recursiveTypeVariableBounds() {
867    assertAssignable(TypeToken.of(new TypeCapture<L>() {}.capture()),
868        TypeToken.of(new TypeCapture<L>() {}.capture()));
869    assertNotAssignable(TypeToken.of(new TypeCapture<R>() {}.capture()),
870        TypeToken.of(new TypeCapture<L>() {}.capture()));
871    assertAssignable(TypeToken.of(new TypeCapture<L>() {}.capture()),
872        new TypeToken<List<R>>() {});
873  }
874
875  public void testIsAssignableFrom_resolved() {
876    assertFalse(Assignability.of().isAssignable());
877    assertTrue(new Assignability<Integer, Integer>() {}.isAssignable());
878    assertTrue(new Assignability<Integer, Object>() {}.isAssignable());
879    assertFalse(new Assignability<Integer, String>() {}.isAssignable());
880    TypeTokenTest.<Number, Integer>assignabilityTestWithTypeVariables();
881  }
882
883  private static <N1 extends Number, N11 extends N1>
884      void assignabilityTestWithTypeVariables() {
885    assertTrue(new Assignability<N11, N1>() {}.isAssignable());
886    assertTrue(new Assignability<N11, Number>() {}.isAssignable());
887    assertFalse(new Assignability<Number, N11>() {}.isAssignable());
888  }
889
890  public void testIsArray_arrayClasses() {
891    assertTrue(TypeToken.of(Object[].class).isArray());
892    assertTrue(TypeToken.of(Object[][].class).isArray());
893    assertTrue(TypeToken.of(char[].class).isArray());
894    assertTrue(TypeToken.of(char[][].class).isArray());
895    assertTrue(TypeToken.of(byte[].class).isArray());
896    assertTrue(TypeToken.of(short[].class).isArray());
897    assertTrue(TypeToken.of(int[].class).isArray());
898    assertTrue(TypeToken.of(long[].class).isArray());
899    assertTrue(TypeToken.of(float[].class).isArray());
900    assertTrue(TypeToken.of(double[].class).isArray());
901    assertFalse(TypeToken.of(Object.class).isArray());
902    assertFalse(TypeToken.of(void.class).isArray());
903  }
904
905  public <T> void testIsArray_genericArrayClasses() {
906    assertFalse(TypeToken.of(new TypeCapture<T>() {}.capture()).isArray());
907    assertTrue(new TypeToken<T[]>() {}.isArray());
908    assertTrue(new TypeToken<T[][]>() {}.isArray());
909  }
910
911  public void testIsArray_wildcardType() throws Exception {
912    assertTrue(TypeToken.of(Types.subtypeOf(Object[].class)).isArray());
913    assertTrue(TypeToken.of(Types.subtypeOf(int[].class)).isArray());
914    assertFalse(TypeToken.of(Types.subtypeOf(Object.class)).isArray());
915    assertFalse(TypeToken.of(Types.supertypeOf(Object[].class)).isArray());
916  }
917
918  public <T extends Integer> void testPrimitiveWrappingAndUnwrapping() {
919    for (Class<?> type : Primitives.allPrimitiveTypes()) {
920      assertIsPrimitive(TypeToken.of(type));
921    }
922    for (Class<?> type : Primitives.allWrapperTypes()) {
923      assertIsWrapper(TypeToken.of(type));
924    }
925    assertNotPrimitiveNorWrapper(TypeToken.of(String.class));
926    assertNotPrimitiveNorWrapper(TypeToken.of(Object[].class));
927    assertNotPrimitiveNorWrapper(TypeToken.of(Types.subtypeOf(Object.class)));
928    assertNotPrimitiveNorWrapper(new TypeToken<List<String>>() {});
929    assertNotPrimitiveNorWrapper(TypeToken.of(new TypeCapture<T>() {}.capture()));
930  }
931
932  public void testGetComponentType_arrayClasses() {
933    assertEquals(Object.class, TypeToken.of(Object[].class).getComponentType().getType());
934    assertEquals(Object[].class, TypeToken.of(Object[][].class).getComponentType().getType());
935    assertEquals(char.class, TypeToken.of(char[].class).getComponentType().getType());
936    assertEquals(char[].class, TypeToken.of(char[][].class).getComponentType().getType());
937    assertEquals(byte.class, TypeToken.of(byte[].class).getComponentType().getType());
938    assertEquals(short.class, TypeToken.of(short[].class).getComponentType().getType());
939    assertEquals(int.class, TypeToken.of(int[].class).getComponentType().getType());
940    assertEquals(long.class, TypeToken.of(long[].class).getComponentType().getType());
941    assertEquals(float.class, TypeToken.of(float[].class).getComponentType().getType());
942    assertEquals(double.class, TypeToken.of(double[].class).getComponentType().getType());
943    assertNull(TypeToken.of(Object.class).getComponentType());
944    assertNull(TypeToken.of(void.class).getComponentType());
945  }
946
947  public <T> void testGetComponentType_genericArrayClasses() {
948    assertNull(TypeToken.of(new TypeCapture<T>() {}.capture()).getComponentType());
949    assertEquals(TypeToken.of(new TypeCapture<T>() {}.capture()),
950        new TypeToken<T[]>() {}.getComponentType());
951    assertEquals(new TypeToken<T[]>() {}, new TypeToken<T[][]>() {}.getComponentType());
952  }
953
954  public void testGetComponentType_wildcardType() throws Exception {
955    assertEquals(Types.subtypeOf(Object.class),
956        TypeToken.of(Types.subtypeOf(Object[].class)).getComponentType().getType());
957    assertEquals(Types.subtypeOf(Object[].class),
958        Types.newArrayType(
959            TypeToken.of(Types.subtypeOf(Object[].class)).getComponentType().getType()));
960    assertEquals(int.class,
961        TypeToken.of(Types.subtypeOf(int[].class)).getComponentType().getType());
962    assertNull(TypeToken.of(Types.subtypeOf(Object.class)).getComponentType());
963    assertNull(TypeToken.of(Types.supertypeOf(Object[].class)).getComponentType());
964  }
965
966  private interface NumberList<T extends Number> {}
967
968  public void testImplicitUpperBoundForWildcards() {
969    assertAssignable(
970        new TypeToken<NumberList<? extends Number>>() {},
971        new TypeToken<NumberList<?>>() {});
972    assertAssignable(
973        new TypeToken<NumberList<? super Integer>>() {},
974        new TypeToken<NumberList<?>>() {});
975  }
976
977  public <T extends Readable & Appendable> void testMultiBound() {
978    assertAssignable(new TypeToken<List<T>>() {},
979        new TypeToken<List<? extends Readable>>() {});
980    assertAssignable(new TypeToken<List<T>>() {},
981        new TypeToken<List<? extends Appendable>>() {});
982  }
983
984  public void testToGenericType() {
985    assertEquals(TypeToken.of(String.class), TypeToken.toGenericType(String.class));
986    assertEquals(new TypeToken<int[]>() {}, TypeToken.toGenericType(int[].class));
987    @SuppressWarnings("rawtypes") // Iterable.class
988    TypeToken<? extends Iterable> genericType = TypeToken.toGenericType(Iterable.class);
989    assertEquals(Iterable.class, genericType.getRawType());
990    assertEquals(Types.newParameterizedType(Iterable.class, Iterable.class.getTypeParameters()[0]),
991        genericType.getType());
992  }
993
994  private interface ListIterable<T> extends Iterable<List<T>> {}
995  private interface StringListIterable extends ListIterable<String> {}
996  private interface ListArrayIterable<T> extends Iterable<List<T>[]> {}
997  private interface StringListArrayIterable extends ListIterable<String> {}
998
999  public void testGetSupertype_withTypeVariable() {
1000    ParameterizedType expectedType = Types.newParameterizedType(Iterable.class,
1001        Types.newParameterizedType(List.class, ListIterable.class.getTypeParameters()[0]));
1002    assertEquals(expectedType,
1003        TypeToken.of(ListIterable.class).getSupertype(Iterable.class).getType());
1004  }
1005
1006  public void testGetSupertype_withoutTypeVariable() {
1007    ParameterizedType expectedType = Types.newParameterizedType(Iterable.class,
1008        Types.newParameterizedType(List.class, String.class));
1009    assertEquals(expectedType,
1010        TypeToken.of(StringListIterable.class).getSupertype(Iterable.class).getType());
1011  }
1012
1013  public void testGetSupertype_chained() {
1014    @SuppressWarnings("unchecked") // StringListIterable extensd ListIterable<String>
1015    TypeToken<ListIterable<String>> listIterableType = (TypeToken<ListIterable<String>>)
1016        TypeToken.of(StringListIterable.class).getSupertype(ListIterable.class);
1017    ParameterizedType expectedType = Types.newParameterizedType(Iterable.class,
1018        Types.newParameterizedType(List.class, String.class));
1019    assertEquals(expectedType, listIterableType.getSupertype(Iterable.class).getType());
1020  }
1021
1022  public void testGetSupertype_withArray() {
1023    assertEquals(new TypeToken<Iterable<List<String>>[]>() {},
1024        TypeToken.of(StringListIterable[].class).getSupertype(Iterable[].class));
1025    assertEquals(int[].class, TypeToken.of(int[].class).getSupertype(int[].class).getType());
1026    assertEquals(Object.class, TypeToken.of(int[].class).getSupertype(Object.class).getType());
1027    assertEquals(int[][].class, TypeToken.of(int[][].class).getSupertype(int[][].class).getType());
1028    assertEquals(Object[].class,
1029        TypeToken.of(String[].class).getSupertype(Object[].class).getType());
1030    assertEquals(Object.class, TypeToken.of(String[].class).getSupertype(Object.class).getType());
1031  }
1032
1033  public void testGetSupertype_fromWildcard() {
1034    @SuppressWarnings("unchecked") // can't do new TypeToken<? extends ...>() {}
1035    TypeToken<? extends List<String>> type = (TypeToken<? extends List<String>>)
1036        TypeToken.of(Types.subtypeOf(new TypeToken<List<String>>() {}.getType()));
1037    assertEquals(new TypeToken<Iterable<String>>() {}, type.getSupertype(Iterable.class));
1038  }
1039
1040  public <T extends Iterable<String>> void testGetSupertype_fromTypeVariable() {
1041    @SuppressWarnings("unchecked") // to construct TypeToken<T> from TypeToken.of()
1042    TypeToken<T> typeVariableToken = (TypeToken<T>) TypeToken.of(new TypeCapture<T>() {}.capture());
1043    assertEquals(new TypeToken<Iterable<String>>() {},
1044        typeVariableToken.getSupertype(Iterable.class));
1045  }
1046
1047  @SuppressWarnings("rawtypes") // purpose is to test raw type
1048  public void testGetSupertype_fromRawClass() {
1049    assertEquals(Types.newParameterizedType(Iterable.class, List.class.getTypeParameters()[0]),
1050        new TypeToken<List>() {}.getSupertype(Iterable.class).getType());
1051  }
1052
1053  @SuppressWarnings({"rawtypes", "unchecked"}) // purpose is to test raw type
1054  public void testGetSupertype_notSupertype() {
1055    try {
1056      new TypeToken<List<String>>() {}.getSupertype((Class) String.class);
1057      fail();
1058    } catch (IllegalArgumentException expected) {}
1059  }
1060
1061  public void testGetSupertype_fromArray() {
1062    assertEquals(new TypeToken<Iterable<String>[]>() {},
1063        new TypeToken<List<String>[]>() {}.getSupertype(Iterable[].class));
1064  }
1065
1066  private interface ListMap<K, V> extends Map<K, List<V>> {}
1067
1068  public void testGetSupertype_fullyGenericType() {
1069    ParameterizedType expectedType = Types.newParameterizedType(Map.class,
1070        ListMap.class.getTypeParameters()[0],
1071        Types.newParameterizedType(List.class, ListMap.class.getTypeParameters()[1]));
1072    assertEquals(expectedType,
1073        TypeToken.of(ListMap.class).getSupertype(Map.class).getType());
1074  }
1075
1076  public void testGetSupertype_fullySpecializedType() {
1077    Type expectedType = new TypeToken<Map<String, List<Object>>>() {}.getType();
1078    assertEquals(expectedType,
1079        new TypeToken<ListMap<String, Object>>() {}.getSupertype(Map.class).getType());
1080  }
1081
1082  private interface StringListMap<V> extends ListMap<String, V> {}
1083
1084  public <V> void testGetSupertype_partiallySpecializedType() {
1085    Type expectedType = new TypeToken<Map<String, List<V>>>() {}.getType();
1086    assertEquals(expectedType,
1087        new TypeToken<StringListMap<V>>() {}.getSupertype(Map.class).getType());
1088  }
1089
1090  public void testGetSubtype_withTypeVariable() {
1091    assertEquals(new TypeToken<ListIterable<String>>() {},
1092        new TypeToken<Iterable<List<String>>>() {}.getSubtype(ListIterable.class));
1093    assertEquals(new TypeToken<ListArrayIterable<String>>() {},
1094        new TypeToken<Iterable<List<String>[]>>() {}.getSubtype(ListArrayIterable.class));
1095    assertEquals(new TypeToken<ListArrayIterable<String>[]>() {},
1096        new TypeToken<Iterable<List<String>[]>[]>() {}.getSubtype(ListArrayIterable[].class));
1097  }
1098
1099  public void testGetSubtype_withoutTypeVariable() {
1100    assertEquals(StringListIterable.class,
1101        TypeToken.of(Iterable.class).getSubtype(StringListIterable.class).getType());
1102    assertEquals(StringListIterable[].class,
1103        TypeToken.of(Iterable[].class).getSubtype(StringListIterable[].class).getType());
1104    assertEquals(TypeToken.of(StringListArrayIterable.class),
1105        new TypeToken<Iterable<List<String>>>() {}.getSubtype(StringListArrayIterable.class));
1106    assertEquals(TypeToken.of(StringListArrayIterable[].class),
1107        new TypeToken<Iterable<List<String>>[]>() {}.getSubtype(StringListArrayIterable[].class));
1108  }
1109
1110  public void testGetSubtype_withArray() {
1111    assertEquals(TypeToken.of(StringListIterable[].class),
1112        TypeToken.of(Iterable[].class).getSubtype(StringListIterable[].class));
1113    assertEquals(TypeToken.of(String[].class),
1114        TypeToken.of(Object[].class).getSubtype(String[].class));
1115    assertEquals(TypeToken.of(int[].class),
1116        TypeToken.of(Object.class).getSubtype(int[].class));
1117  }
1118
1119  public void testGetSubtype_fromWildcard() {
1120    @SuppressWarnings("unchecked") // can't do new TypeToken<? extends ...>() {}
1121    TypeToken<? super Iterable<String>> type = (TypeToken<? super Iterable<String>>)
1122        TypeToken.of(Types.supertypeOf(new TypeToken<Iterable<String>>() {}.getType()));
1123    assertEquals(new TypeToken<List<String>>() {}, type.getSubtype(List.class));
1124  }
1125
1126  public void testGetSubtype_fromWildcard_lowerBoundNotSupertype() {
1127    @SuppressWarnings("unchecked") // can't do new TypeToken<? extends ...>() {}
1128    TypeToken<? super Iterable<String>> type = (TypeToken<? super Iterable<String>>)
1129        TypeToken.of(Types.supertypeOf(new TypeToken<ImmutableList<String>>() {}.getType()));
1130    try {
1131      type.getSubtype(List.class);
1132      fail();
1133    } catch (IllegalArgumentException expected) {}
1134  }
1135
1136  public void testGetSubtype_fromWildcard_upperBounded() {
1137    @SuppressWarnings("unchecked") // can't do new TypeToken<? extends ...>() {}
1138    TypeToken<? extends Iterable<String>> type = (TypeToken<? extends Iterable<String>>)
1139        TypeToken.of(Types.subtypeOf(new TypeToken<Iterable<String>>() {}.getType()));
1140    try {
1141      type.getSubtype(Iterable.class);
1142      fail();
1143    } catch (IllegalArgumentException expected) {}
1144  }
1145
1146  public <T extends Iterable<String>> void testGetSubtype_fromTypeVariable() {
1147    try {
1148      TypeToken.of(new TypeCapture<T>() {}.capture()).getSubtype(List.class);
1149      fail();
1150    } catch (IllegalArgumentException expected) {}
1151  }
1152
1153  @SuppressWarnings("rawtypes") // purpose is to test raw type
1154  public void testGetSubtype_fromRawClass() {
1155    assertEquals(List.class, new TypeToken<Iterable>() {}.getSubtype(List.class).getType());
1156  }
1157
1158  public void testGetSubtype_fromArray() {
1159    assertEquals(new TypeToken<List<String>[]>() {},
1160        new TypeToken<Iterable<String>[]>() {}.getSubtype(List[].class));
1161  }
1162
1163  @SuppressWarnings("unchecked") // To construct TypeToken<T> with TypeToken.of()
1164  public <T> void testWhere_circleRejected() {
1165    TypeToken<List<T>> type = new TypeToken<List<T>>() {};
1166    try {
1167      type.where(new TypeParameter<T>() {},
1168          (TypeToken<T>) TypeToken.of(new TypeCapture<T>() {}.capture()));
1169      fail();
1170    } catch (IllegalArgumentException expected) {}
1171  }
1172
1173  public void testWhere() {
1174    assertEquals(
1175        new TypeToken<Map<String, Integer>>() {},
1176        mapOf(String.class, Integer.class));
1177    assertEquals(new TypeToken<int[]>() {}, arrayOf(int.class));
1178    assertEquals(int[].class, arrayOf(int.class).getRawType());
1179  }
1180
1181  @SuppressWarnings("unused") // used by reflection
1182  private static class Holder<T> {
1183    T element;
1184    List<T> list;
1185    List<T>[] matrix;
1186
1187    void setList(List<T> list) {
1188      this.list = list;
1189    }
1190  }
1191
1192  public void testWildcardCaptured_methodParameter_upperBound() throws Exception {
1193    TypeToken<Holder<?>> type = new TypeToken<Holder<?>>() {};
1194    TypeToken<?> parameterType = type.resolveType(
1195        Holder.class.getDeclaredMethod("setList", List.class).getGenericParameterTypes()[0]);
1196    assertEquals(List.class, parameterType.getRawType());
1197    assertFalse(parameterType.getType().toString(),
1198        parameterType.isAssignableFrom(new TypeToken<List<Integer>>() {}));
1199  }
1200
1201  public void testWildcardCaptured_field_upperBound() throws Exception {
1202    TypeToken<Holder<?>> type = new TypeToken<Holder<?>>() {};
1203    TypeToken<?> matrixType = type.resolveType(
1204        Holder.class.getDeclaredField("matrix").getGenericType());
1205    assertEquals(List[].class, matrixType.getRawType());
1206    assertThat(matrixType.getType())
1207        .isNotEqualTo(new TypeToken<List<?>[]>() {}.getType());
1208  }
1209
1210  public void testArrayClassPreserved() {
1211    assertEquals(int[].class, TypeToken.of(int[].class).getType());
1212    assertEquals(int[][].class, TypeToken.of(int[][].class).getType());
1213    assertEquals(String[].class, TypeToken.of(String[].class).getType());
1214    assertEquals(Integer.class, new TypeToken<Integer>() {}.getType());
1215    assertEquals(Integer.class, TypeToken.of(Integer.class).getType());
1216  }
1217
1218  public void testMethod_getOwnerType() throws NoSuchMethodException {
1219    Method sizeMethod = List.class.getMethod("size");
1220    assertEquals(TypeToken.of(List.class),
1221        TypeToken.of(List.class).method(sizeMethod).getOwnerType());
1222    assertEquals(new TypeToken<List<String>>() {},
1223        new TypeToken<List<String>>() {}.method(sizeMethod).getOwnerType());
1224  }
1225
1226  public void testMethod_notDeclaredByType() throws NoSuchMethodException {
1227    Method sizeMethod = Map.class.getMethod("size");
1228    try {
1229      TypeToken.of(List.class).method(sizeMethod);
1230      fail();
1231    } catch (IllegalArgumentException expected) {}
1232  }
1233
1234  public void testMethod_declaredBySuperclass() throws Exception {
1235    Method toStringMethod = Object.class.getMethod("toString");
1236    ImmutableList<String> list = ImmutableList.of("foo");
1237    assertEquals(list.toString(), TypeToken.of(List.class).method(toStringMethod).invoke(list));
1238  }
1239
1240  public <T extends Number & List<String>> void testMethod_returnType_resolvedAgainstTypeBound()
1241      throws NoSuchMethodException {
1242    Method getMethod = List.class.getMethod("get", int.class);
1243    Invokable<T, String> invokable = new TypeToken<T>(getClass()) {}
1244        .method(getMethod)
1245        .returning(String.class);
1246    assertEquals(TypeToken.of(String.class), invokable.getReturnType());
1247  }
1248
1249  public <T extends List<String>> void testMethod_parameterTypes()
1250      throws NoSuchMethodException {
1251    Method setMethod = List.class.getMethod("set", int.class, Object.class);
1252    Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.method(setMethod);
1253    ImmutableList<Parameter> params = invokable.getParameters();
1254    assertEquals(2, params.size());
1255    assertEquals(TypeToken.of(int.class), params.get(0).getType());
1256    assertEquals(TypeToken.of(String.class), params.get(1).getType());
1257  }
1258
1259  public void testMethod_equals() throws NoSuchMethodException {
1260    Method getMethod = List.class.getMethod("get", int.class);
1261    Method setMethod = List.class.getMethod("set", int.class, Object.class);
1262    new EqualsTester()
1263        .addEqualityGroup(Invokable.from(getMethod), Invokable.from(getMethod))
1264        .addEqualityGroup(Invokable.from(setMethod))
1265        .addEqualityGroup(new TypeToken<List<Integer>>() {}.method(getMethod))
1266        .addEqualityGroup(new TypeToken<List<String>>() {}.method(getMethod))
1267        .addEqualityGroup(new TypeToken<List<Integer>>() {}.method(setMethod))
1268        .addEqualityGroup(new TypeToken<List<String>>() {}.method(setMethod))
1269        .testEquals();
1270  }
1271
1272  private interface Loser<E extends Throwable> {
1273    void lose() throws E;
1274  }
1275
1276  public <T extends Loser<AssertionError>> void testMethod_exceptionTypes()
1277      throws NoSuchMethodException {
1278    Method failMethod = Loser.class.getMethod("lose");
1279    Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.method(failMethod);
1280    assertThat(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class));
1281  }
1282
1283  public void testConstructor_getOwnerType() throws NoSuchMethodException {
1284    @SuppressWarnings("rawtypes") // raw class ArrayList.class
1285    Constructor<ArrayList> constructor = ArrayList.class.getConstructor();
1286    assertEquals(TypeToken.of(ArrayList.class),
1287        TypeToken.of(ArrayList.class).constructor(constructor).getOwnerType());
1288    assertEquals(new TypeToken<ArrayList<String>>() {},
1289        new TypeToken<ArrayList<String>>() {}.constructor(constructor).getOwnerType());
1290  }
1291
1292  public void testConstructor_notDeclaredByType() throws NoSuchMethodException {
1293    Constructor<String> constructor = String.class.getConstructor();
1294    try {
1295      TypeToken.of(Object.class).constructor(constructor);
1296      fail();
1297    } catch (IllegalArgumentException expected) {}
1298  }
1299
1300  public void testConstructor_declaredBySuperclass() throws NoSuchMethodException {
1301    Constructor<Object> constructor = Object.class.getConstructor();
1302    try {
1303      TypeToken.of(String.class).constructor(constructor);
1304      fail();
1305    } catch (IllegalArgumentException expected) {}
1306  }
1307
1308  public void testConstructor_equals() throws NoSuchMethodException {
1309    Constructor<?> defaultConstructor = ArrayList.class.getConstructor();
1310    Constructor<?> oneArgConstructor = ArrayList.class.getConstructor(int.class);
1311    new EqualsTester()
1312        .addEqualityGroup(Invokable.from(defaultConstructor), Invokable.from(defaultConstructor))
1313        .addEqualityGroup(Invokable.from(oneArgConstructor))
1314        .addEqualityGroup(new TypeToken<ArrayList<Integer>>() {}.constructor(defaultConstructor))
1315        .addEqualityGroup(new TypeToken<ArrayList<String>>() {}.constructor(defaultConstructor))
1316        .addEqualityGroup(new TypeToken<ArrayList<Integer>>() {}.constructor(oneArgConstructor))
1317        .addEqualityGroup(new TypeToken<ArrayList<String>>() {}.constructor(oneArgConstructor))
1318        .testEquals();
1319  }
1320
1321  private static class Container<T> {
1322    @SuppressWarnings("unused")
1323    public Container(T data) {}
1324  }
1325
1326  public <T extends Container<String>> void testConstructor_parameterTypes()
1327      throws NoSuchMethodException {
1328    @SuppressWarnings("rawtypes") // Reflection API skew
1329    Constructor<Container> constructor = Container.class.getConstructor(Object.class);
1330    Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.constructor(constructor);
1331    ImmutableList<Parameter> params = invokable.getParameters();
1332    assertEquals(1, params.size());
1333    assertEquals(TypeToken.of(String.class), params.get(0).getType());
1334  }
1335
1336  private static class CannotConstruct<E extends Throwable> {
1337    @SuppressWarnings("unused")
1338    public CannotConstruct() throws E {}
1339  }
1340
1341  public <T extends CannotConstruct<AssertionError>> void testConstructor_exceptionTypes()
1342      throws NoSuchMethodException {
1343    @SuppressWarnings("rawtypes") // Reflection API skew
1344    Constructor<CannotConstruct> constructor = CannotConstruct.class.getConstructor();
1345    Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.constructor(constructor);
1346    assertThat(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class));
1347  }
1348
1349  public void testRejectTypeVariable_class() {
1350    assertNoTypeVariable(String.class);
1351    assertNoTypeVariable(String[].class);
1352    assertNoTypeVariable(int[].class);
1353  }
1354
1355  public void testRejectTypeVariable_parameterizedType() {
1356    assertNoTypeVariable(new TypeCapture<Iterable<String>>() {}.capture());
1357  }
1358
1359  public void testRejectTypeVariable_wildcardType() {
1360    assertNoTypeVariable(
1361        new TypeCapture<Iterable<? extends String>>() {}.capture());
1362    assertNoTypeVariable(
1363        new TypeCapture<Iterable<? super String>>() {}.capture());
1364  }
1365
1366  public void testRejectTypeVariable_genericArrayType() {
1367    assertNoTypeVariable(
1368        new TypeCapture<Iterable<? extends String>[]>() {}.capture());
1369  }
1370
1371  public <T> void testRejectTypeVariable_withTypeVariable() {
1372    assertHasTypeVariable(new TypeCapture<T>() {}.capture());
1373    assertHasTypeVariable(new TypeCapture<T[]>() {}.capture());
1374    assertHasTypeVariable(new TypeCapture<Iterable<T>>() {}.capture());
1375    assertHasTypeVariable(new TypeCapture<Map<String, T>>() {}.capture());
1376    assertHasTypeVariable(
1377        new TypeCapture<Map<String, ? extends T>>() {}.capture());
1378    assertHasTypeVariable(
1379        new TypeCapture<Map<String, ? super T[]>>() {}.capture());
1380  }
1381
1382  private static class From<K> {
1383    class To<V> {
1384      Type type() {
1385        return new TypeToken<To<V>>(getClass()) {}.getType();
1386      }
1387    }
1388  }
1389
1390  public <T> void testRejectTypeVariable_withOwnerType() {
1391    // Neither has subclass
1392    assertHasTypeVariable(new From<Integer>().new To<String>().type());
1393    assertHasTypeVariable(new From<T>().new To<String>().type());
1394    assertHasTypeVariable(new From<Integer>().new To<T>().type());
1395
1396    // Owner is subclassed
1397    assertHasTypeVariable(new From<Integer>() {}.new To<String>().type());
1398    assertHasTypeVariable(new From<T>() {}.new To<String>().type());
1399
1400    // Inner is subclassed
1401    assertNoTypeVariable(new From<Integer>().new To<String>() {}.type());
1402    assertHasTypeVariable(new From<Integer>().new To<T>() {}.type());
1403    assertHasTypeVariable(new From<T>().new To<String>() {}.type());
1404
1405    // both subclassed
1406    assertHasTypeVariable(new From<T>() {}.new To<String>() {}.type());
1407    assertNoTypeVariable(new From<Integer>() {}.new To<String>() {}.type());
1408    assertHasTypeVariable(new From<Integer>() {}.new To<T>() {}.type());
1409  }
1410
1411  private static void assertHasTypeVariable(Type type) {
1412    try {
1413      TypeToken.of(type).rejectTypeVariables();
1414      fail("Should contain TypeVariable");
1415    } catch (IllegalArgumentException expected) {}
1416  }
1417
1418  private static void assertNoTypeVariable(Type type) {
1419    TypeToken.of(type).rejectTypeVariables();
1420  }
1421
1422  private abstract static class RawTypeConsistencyTester<T extends Enum<T> & CharSequence> {
1423    abstract T returningT();
1424    abstract void acceptT(T t);
1425    abstract <X extends T> X returningX();
1426    abstract <X> void acceptX(X x);
1427    abstract <T2 extends Enum<T2> & CharSequence> T2 returningT2();
1428    abstract <T2 extends CharSequence&Iterable<T2>> void acceptT2(T2 t2);
1429
1430    static void verifyConsitentRawType() {
1431      for (Method method : RawTypeConsistencyTester.class.getDeclaredMethods()) {
1432        assertEquals(method.getReturnType(), TypeToken.getRawType(method.getGenericReturnType()));
1433        for (int i = 0; i < method.getParameterTypes().length; i++) {
1434          assertEquals(method.getParameterTypes()[i],
1435              TypeToken.getRawType(method.getGenericParameterTypes()[i]));
1436        }
1437      }
1438    }
1439  }
1440
1441  public void testRawTypes() throws Exception {
1442    RawTypeConsistencyTester.verifyConsitentRawType();
1443    assertEquals(Object.class, TypeToken.getRawType(Types.subtypeOf(Object.class)));
1444    assertEquals(CharSequence.class, TypeToken.getRawType(Types.subtypeOf(CharSequence.class)));
1445    assertEquals(Object.class, TypeToken.getRawType(Types.supertypeOf(CharSequence.class)));
1446  }
1447
1448  private abstract static class IKnowMyType<T> {
1449    TypeToken<T> type() {
1450      return new TypeToken<T>(getClass()) {};
1451    }
1452  }
1453
1454  public void testTypeResolution() {
1455    assertEquals(String.class,
1456        new IKnowMyType<String>() {}.type().getType());
1457    assertEquals(new TypeToken<Map<String, Integer>>() {},
1458        new IKnowMyType<Map<String, Integer>>() {}.type());
1459  }
1460
1461  public <A extends Iterable<? extends String>, B extends A> void testSerializable() {
1462    reserialize(TypeToken.of(String.class));
1463    reserialize(TypeToken.of(String.class).getTypes());
1464    reserialize(TypeToken.of(String.class).getTypes().classes());
1465    reserialize(TypeToken.of(String.class).getTypes().interfaces());
1466    reserialize(TypeToken.of(String.class).getTypes().rawTypes());
1467    reserialize(TypeToken.of(String.class).getTypes().classes().rawTypes());
1468    reserialize(TypeToken.of(String.class).getTypes().interfaces().rawTypes());
1469    reserialize(new TypeToken<int[]>() {});
1470    reserialize(new TypeToken<Map<String, Integer>>() {});
1471    reserialize(new IKnowMyType<Map<? super String, ? extends int[]>>() {}.type());
1472    reserialize(TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes().rawTypes());
1473    try {
1474      SerializableTester.reserialize(TypeToken.of(new TypeCapture<B>() {}.capture()));
1475      fail();
1476    } catch (RuntimeException expected) {}
1477  }
1478
1479  public <A> void testSerializable_typeVariableNotSupported() {
1480    try {
1481      new ITryToSerializeMyTypeVariable<String>().go();
1482      fail();
1483    } catch (RuntimeException expected) {}
1484  }
1485
1486  private static class ITryToSerializeMyTypeVariable<T> {
1487    void go() {
1488      SerializableTester.reserialize(TypeToken.of(new TypeCapture<T>() {}.capture()));
1489    }
1490  }
1491
1492  private static <T> T reserialize(T object) {
1493    T copy = SerializableTester.reserialize(object);
1494    new EqualsTester()
1495        .addEqualityGroup(object, copy)
1496        .testEquals();
1497    return copy;
1498  }
1499
1500  public void testTypeResolutionAfterReserialized() {
1501    reserialize(new TypeToken<String>() {});
1502    reserialize(new TypeToken<Map<String, Integer>>() {});
1503    TypeToken<Map<String, Integer>> reserialized = reserialize(
1504        new TypeToken<Map<String, Integer>>() {});
1505    assertEquals(reserialized, substitute(reserialized, String.class));
1506  }
1507
1508  private static <T, X> TypeToken<T> substitute(TypeToken<T> type, Class<X> arg) {
1509    return type.where(new TypeParameter<X>() {}, arg);
1510  }
1511
1512  private abstract static class ToReproduceGenericSignatureFormatError<V> {
1513    private abstract class BaseOuter {
1514      abstract class BaseInner {}
1515    }
1516    private abstract class SubOuter extends BaseOuter {
1517      private abstract class SubInner extends BaseInner {}
1518    }
1519  }
1520
1521  // For Guava bug http://code.google.com/p/guava-libraries/issues/detail?id=1025
1522  public void testDespiteGenericSignatureFormatError() {
1523    ImmutableSet.copyOf(
1524        TypeToken.of(ToReproduceGenericSignatureFormatError.SubOuter.SubInner.class)
1525            .getTypes()
1526            .rawTypes());
1527  }
1528
1529  private abstract static class Entry<K, V> {
1530    TypeToken<K> keyType() {
1531      return new TypeToken<K>(getClass()) {};
1532    }
1533    TypeToken<V> valueType() {
1534      return new TypeToken<V>(getClass()) {};
1535    }
1536  }
1537
1538  // The A and B type parameters are used inside the test to test type variable
1539  public <A, B> void testEquals() {
1540    new EqualsTester()
1541        .addEqualityGroup(
1542            TypeToken.of(String.class),
1543            TypeToken.of(String.class),
1544            new Entry<String, Integer>() {}.keyType(),
1545            new Entry<Integer, String>() {}.valueType(),
1546            new TypeToken<String>() {},
1547            new TypeToken<String>() {})
1548        .addEqualityGroup(
1549            TypeToken.of(Integer.class),
1550            new TypeToken<Integer>() {},
1551            new Entry<Integer, String>() {}.keyType(),
1552            new Entry<String, Integer>() {}.valueType())
1553        .addEqualityGroup(
1554            new TypeToken<List<String>>() {},
1555            new TypeToken<List<String>>() {})
1556        .addEqualityGroup(
1557            new TypeToken<List<?>>() {},
1558            new TypeToken<List<?>>() {})
1559        .addEqualityGroup(
1560            new TypeToken<Map<A, ?>>() {},
1561            new TypeToken<Map<A, ?>>() {})
1562        .addEqualityGroup(
1563            new TypeToken<Map<B, ?>>() {})
1564        .addEqualityGroup(
1565            TypeToken.of(new TypeCapture<A>() {}.capture()),
1566            TypeToken.of(new TypeCapture<A>() {}.capture()))
1567        .addEqualityGroup(TypeToken.of(new TypeCapture<B>() {}.capture()))
1568        .testEquals();
1569  }
1570
1571  // T is used inside to test type variable
1572  public <T> void testToString() {
1573    assertEquals(String.class.getName(), new TypeToken<String>() {}.toString());
1574    assertEquals("T", TypeToken.of(new TypeCapture<T>() {}.capture()).toString());
1575    assertEquals("java.lang.String", new Entry<String, Integer>() {}.keyType().toString());
1576  }
1577
1578  private static <K, V> TypeToken<Map<K, V>> mapOf(Class<K> keyType, Class<V> valueType) {
1579    return new TypeToken<Map<K, V>>() {}
1580        .where(new TypeParameter<K>() {}, keyType)
1581        .where(new TypeParameter<V>() {}, valueType);
1582  }
1583
1584  private static <T> TypeToken<T[]> arrayOf(Class<T> componentType) {
1585    return new TypeToken<T[]>() {}
1586        .where(new TypeParameter<T>() {}, componentType);
1587  }
1588
1589  public <T> void testNulls() {
1590    new NullPointerTester()
1591        .testAllPublicStaticMethods(TypeToken.class);
1592    new NullPointerTester()
1593        .setDefault(TypeParameter.class, new TypeParameter<T>() {})
1594        .testAllPublicInstanceMethods(TypeToken.of(String.class));
1595  }
1596
1597  private static class Assignability<From, To> {
1598
1599    boolean isAssignable() {
1600      return new TypeToken<To>(getClass()) {}.isAssignableFrom(new TypeToken<From>(getClass()) {});
1601    }
1602
1603    static <From, To> Assignability<From, To> of() {
1604      return new Assignability<From, To>();
1605    }
1606  }
1607
1608  private static void assertAssignable(TypeToken<?> from, TypeToken<?> to) {
1609    assertTrue(
1610        from.getType() + " is expected to be assignable to " + to.getType(),
1611        to.isAssignableFrom(from));
1612  }
1613
1614  private static void assertNotAssignable(TypeToken<?> from, TypeToken<?> to) {
1615    assertFalse(
1616        from.getType() + " shouldn't be assignable to " + to.getType(),
1617        to.isAssignableFrom(from));
1618  }
1619
1620  private static void assertHasArrayInterfaces(TypeToken<?> arrayType) {
1621    assertEquals(arrayInterfaces(), ImmutableSet.copyOf(arrayType.getGenericInterfaces()));
1622  }
1623
1624  private static ImmutableSet<TypeToken<?>> arrayInterfaces() {
1625    ImmutableSet.Builder<TypeToken<?>> builder = ImmutableSet.builder();
1626    for (Class<?> interfaceType : Object[].class.getInterfaces()) {
1627      builder.add(TypeToken.of(interfaceType));
1628    }
1629    return builder.build();
1630  }
1631
1632  private static void assertIsPrimitive(TypeToken<?> type) {
1633    assertTrue(type.isPrimitive());
1634    assertNotWrapper(type);
1635    assertEquals(TypeToken.of(Primitives.wrap((Class<?>) type.getType())), type.wrap());
1636  }
1637
1638  private static void assertNotPrimitive(TypeToken<?> type) {
1639    assertFalse(type.isPrimitive());
1640    assertSame(type, type.wrap());
1641  }
1642
1643  private static void assertIsWrapper(TypeToken<?> type) {
1644    assertNotPrimitive(type);
1645    assertEquals(TypeToken.of(Primitives.unwrap((Class<?>) type.getType())), type.unwrap());
1646  }
1647
1648  private static void assertNotWrapper(TypeToken<?> type) {
1649    assertSame(type, type.unwrap());
1650  }
1651
1652  private static void assertNotPrimitiveNorWrapper(TypeToken<?> type) {
1653    assertNotPrimitive(type);
1654    assertNotWrapper(type);
1655  }
1656
1657  private interface BaseInterface {}
1658  private static class Base implements BaseInterface {}
1659  private static class Sub extends Base {}
1660
1661  private static CollectionSubject<?, Object, ?> makeUnmodifiable(Collection<?> actual) {
1662    return assertThat(Collections.<Object>unmodifiableCollection(actual));
1663  }
1664}
1665