17dd252788645e940eada959bdde927426e2531c9Paul Duffin/*
27dd252788645e940eada959bdde927426e2531c9Paul Duffin * Copyright (C) 2007 The Guava Authors
37dd252788645e940eada959bdde927426e2531c9Paul Duffin *
47dd252788645e940eada959bdde927426e2531c9Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
57dd252788645e940eada959bdde927426e2531c9Paul Duffin * you may not use this file except in compliance with the License.
67dd252788645e940eada959bdde927426e2531c9Paul Duffin * You may obtain a copy of the License at
77dd252788645e940eada959bdde927426e2531c9Paul Duffin *
87dd252788645e940eada959bdde927426e2531c9Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
97dd252788645e940eada959bdde927426e2531c9Paul Duffin *
107dd252788645e940eada959bdde927426e2531c9Paul Duffin * Unless required by applicable law or agreed to in writing, software
117dd252788645e940eada959bdde927426e2531c9Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
127dd252788645e940eada959bdde927426e2531c9Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137dd252788645e940eada959bdde927426e2531c9Paul Duffin * See the License for the specific language governing permissions and
147dd252788645e940eada959bdde927426e2531c9Paul Duffin * limitations under the License.
157dd252788645e940eada959bdde927426e2531c9Paul Duffin */
167dd252788645e940eada959bdde927426e2531c9Paul Duffin
177dd252788645e940eada959bdde927426e2531c9Paul Duffinpackage com.google.common.reflect;
187dd252788645e940eada959bdde927426e2531c9Paul Duffin
197dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static org.truth0.Truth.ASSERT;
207dd252788645e940eada959bdde927426e2531c9Paul Duffin
217dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.base.Function;
227dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ImmutableList;
237dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ImmutableMap;
247dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ImmutableSet;
257dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.Maps;
260888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.primitives.Primitives;
277dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.testing.EqualsTester;
287dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.testing.NullPointerTester;
297dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.testing.SerializableTester;
307dd252788645e940eada959bdde927426e2531c9Paul Duffin
310888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport junit.framework.TestCase;
320888a09821a98ac0680fad765217302858e70fa4Paul Duffin
330888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport org.truth0.subjects.CollectionSubject;
340888a09821a98ac0680fad765217302858e70fa4Paul Duffin
357dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.io.Serializable;
367dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Constructor;
377dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.GenericArrayType;
387dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Method;
397dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.ParameterizedType;
407dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Type;
417dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.ArrayList;
427dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Collection;
430888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Collections;
447dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.List;
457dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Map;
467dd252788645e940eada959bdde927426e2531c9Paul Duffin
477dd252788645e940eada959bdde927426e2531c9Paul Duffin/**
487dd252788645e940eada959bdde927426e2531c9Paul Duffin * Test cases for {@link TypeToken}.
497dd252788645e940eada959bdde927426e2531c9Paul Duffin *
507dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Sven Mawson
517dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Ben Yu
527dd252788645e940eada959bdde927426e2531c9Paul Duffin */
537dd252788645e940eada959bdde927426e2531c9Paul Duffinpublic class TypeTokenTest extends TestCase {
547dd252788645e940eada959bdde927426e2531c9Paul Duffin
557dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class StringList implements List<String> {}
567dd252788645e940eada959bdde927426e2531c9Paul Duffin
577dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class IntegerList implements List<Integer> {}
587dd252788645e940eada959bdde927426e2531c9Paul Duffin
597dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testValueEqualityNotInstanceEquality() {
607dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>> a = new TypeToken<List<String>>() {};
617dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>> b = new TypeToken<List<String>>() {};
627dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(a, b);
637dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
647dd252788645e940eada959bdde927426e2531c9Paul Duffin
657dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testVariableTypeTokenNotAllowed() {
667dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
677dd252788645e940eada959bdde927426e2531c9Paul Duffin      new TypeToken<T>() {};
687dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
697dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalStateException expected) {}
707dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
717dd252788645e940eada959bdde927426e2531c9Paul Duffin
727dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testRawTypeIsCorrect() {
737dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>> token = new TypeToken<List<String>>() {};
747dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(List.class, token.getRawType());
757dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
767dd252788645e940eada959bdde927426e2531c9Paul Duffin
777dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testTypeIsCorrect() {
787dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>> token = new TypeToken<List<String>>() {};
797dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(StringList.class.getGenericInterfaces()[0], token.getType());
807dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
817dd252788645e940eada959bdde927426e2531c9Paul Duffin
820888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("rawtypes") // Trying to test TypeToken.of(List.class)
837dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetClass() {
847dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List> token = TypeToken.of(List.class);
857dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<List>() {}, token);
867dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
877dd252788645e940eada959bdde927426e2531c9Paul Duffin
887dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetType() {
897dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> t = TypeToken.of(StringList.class.getGenericInterfaces()[0]);
907dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<List<String>>() {}, t);
917dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
927dd252788645e940eada959bdde927426e2531c9Paul Duffin
937dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNonStaticLocalClass() {
947dd252788645e940eada959bdde927426e2531c9Paul Duffin    class Local<T> {}
957dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Local<String>> type = new TypeToken<Local<String>>() {};
967dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Types.newParameterizedType(Local.class, String.class),
977dd252788645e940eada959bdde927426e2531c9Paul Duffin        type.getType());
987dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new Local<String>() {}.getClass().getGenericSuperclass(), type.getType());
997dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1007dd252788645e940eada959bdde927426e2531c9Paul Duffin
1017dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testStaticLocalClass() {
1027dd252788645e940eada959bdde927426e2531c9Paul Duffin    doTestStaticLocalClass();
1037dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1047dd252788645e940eada959bdde927426e2531c9Paul Duffin
1057dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void doTestStaticLocalClass() {
1067dd252788645e940eada959bdde927426e2531c9Paul Duffin    class Local<T> {}
1077dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Local<String>> type = new TypeToken<Local<String>>() {};
1087dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Types.newParameterizedType(Local.class, String.class),
1097dd252788645e940eada959bdde927426e2531c9Paul Duffin        type.getType());
1107dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new Local<String>() {}.getClass().getGenericSuperclass(), type.getType());
1117dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1127dd252788645e940eada959bdde927426e2531c9Paul Duffin
1137dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGenericArrayType() throws Exception {
1147dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>[]> token = new TypeToken<List<String>[]>() {};
1157dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(List[].class, token.getRawType());
1167dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(token.getType() instanceof GenericArrayType);
1177dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1187dd252788645e940eada959bdde927426e2531c9Paul Duffin
1197dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testMultiDimensionalGenericArrayType() throws Exception {
1207dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<Long>[][][]> token = new TypeToken<List<Long>[][][]>() {};
1217dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(List[][][].class, token.getRawType());
1227dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(token.getType() instanceof GenericArrayType);
1237dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1247dd252788645e940eada959bdde927426e2531c9Paul Duffin
1257dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testGenericVariableTypeArrays() throws Exception {
1267dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals("T[]", new TypeToken<T[]>() {}.toString());
1277dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1287dd252788645e940eada959bdde927426e2531c9Paul Duffin
1297dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testResolveType() throws Exception {
1307dd252788645e940eada959bdde927426e2531c9Paul Duffin    Method getFromList = List.class.getMethod("get", int.class);
1317dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> returnType = new TypeToken<List<String>>() {}
1327dd252788645e940eada959bdde927426e2531c9Paul Duffin        .resolveType(getFromList.getGenericReturnType());
1337dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(String.class, returnType.getType());
1347dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1357dd252788645e940eada959bdde927426e2531c9Paul Duffin
1367dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <F extends Enum<F> & Function<String, Integer> & Iterable<Long>>
1377dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testResolveType_fromTypeVariable() throws Exception {
1387dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> f = TypeToken.of(new TypeCapture<F>() {}.capture());
1397dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(String.class,
1407dd252788645e940eada959bdde927426e2531c9Paul Duffin        f.resolveType(Function.class.getTypeParameters()[0]).getType());
1417dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Integer.class,
1427dd252788645e940eada959bdde927426e2531c9Paul Duffin        f.resolveType(Function.class.getTypeParameters()[1]).getType());
1437dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Long.class,
1447dd252788645e940eada959bdde927426e2531c9Paul Duffin        f.resolveType(Iterable.class.getTypeParameters()[0]).getType());
1457dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1467dd252788645e940eada959bdde927426e2531c9Paul Duffin
1477dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <E extends Comparable<Iterable<String>> & Iterable<Integer>>
1487dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testResolveType_fromTypeVariable_onlyDirectBoundsAreUsed() throws Exception {
1497dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> e = TypeToken.of(new TypeCapture<E>() {}.capture());
1507dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Integer.class,
1517dd252788645e940eada959bdde927426e2531c9Paul Duffin        e.resolveType(Iterable.class.getTypeParameters()[0]).getType());
1527dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1537dd252788645e940eada959bdde927426e2531c9Paul Duffin
1547dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testResolveType_fromWildcard() throws Exception {
1557dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType withWildcardType = (ParameterizedType)
1567dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeCapture<Comparable<? extends Iterable<String>>>() {}.capture();
1577dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> wildcardType = TypeToken.of(withWildcardType.getActualTypeArguments()[0]);
1587dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(String.class,
1597dd252788645e940eada959bdde927426e2531c9Paul Duffin        wildcardType.resolveType(Iterable.class.getTypeParameters()[0]).getType());
1607dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1617dd252788645e940eada959bdde927426e2531c9Paul Duffin
1627dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetTypes_noSuperclass() {
1637dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Object>.TypeSet types = new TypeToken<Object>() {}.getTypes();
1640888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types).has().item(TypeToken.of(Object.class));
1650888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.rawTypes()).has().item(Object.class);
1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.interfaces()).isEmpty();
1670888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.interfaces().rawTypes()).isEmpty();
1680888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.classes()).has().item(TypeToken.of(Object.class));
1690888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.classes().rawTypes()).has().item(Object.class);
1707dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1717dd252788645e940eada959bdde927426e2531c9Paul Duffin
1727dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetTypes_fromInterface() {
1737dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Interface1>.TypeSet types = new TypeToken<Interface1>() {}.getTypes();
1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types).has().item(TypeToken.of(Interface1.class));
1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.rawTypes()).has().item(Interface1.class);
1760888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.interfaces()).has().item(TypeToken.of(Interface1.class));
1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.interfaces().rawTypes()).has().item(Interface1.class);
1780888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.classes()).isEmpty();
1790888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.classes().rawTypes()).isEmpty();
1807dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1817dd252788645e940eada959bdde927426e2531c9Paul Duffin
1827dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetTypes_fromPrimitive() {
1837dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Integer>.TypeSet types = TypeToken.of(int.class).getTypes();
1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types).has().item(TypeToken.of(int.class));
1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.rawTypes()).has().item(int.class);
1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.interfaces()).isEmpty();
1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.interfaces().rawTypes()).isEmpty();
1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.classes()).has().item(TypeToken.of(int.class));
1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(types.classes().rawTypes()).has().item(int.class);
1907dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1917dd252788645e940eada959bdde927426e2531c9Paul Duffin
1927dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetTypes_withInterfacesAndSuperclasses() {
1937dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract class Class2 extends Class1 implements Interface12 {}
1947dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract class Class3<T> extends Class2 implements Interface3<T> {}
1957dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Class3<String>>.TypeSet types = new TypeToken<Class3<String>>() {}.getTypes();
1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types).has().exactly(
1977dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Class3<String>>() {},
1987dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Interface3<String>>() {},
1997dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Iterable<String>>() {},
2007dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Class2.class),
2017dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Interface12.class),
2027dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Interface1.class),
2037dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Interface2.class),
2047dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Class1.class),
2057dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Object.class));
2060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.interfaces()).has().exactly(
2077dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Interface3<String>>() {},
2087dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Interface12.class),
2097dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Interface1.class),
2107dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Interface2.class),
2117dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Iterable<String>>() {});
2120888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.classes()).has().exactly(
2137dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Class3<String>>() {},
2147dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Class2.class),
2157dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Class1.class),
2167dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Object.class));
2177dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeFirst(types);
2187dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2197dd252788645e940eada959bdde927426e2531c9Paul Duffin
2207dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetTypes_rawTypes_withInterfacesAndSuperclasses() {
2217dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract class Class2 extends Class1 implements Interface12 {}
2227dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract class Class3<T> extends Class2 implements Interface3<T> {}
2237dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Class3<String>>.TypeSet types = new TypeToken<Class3<String>>() {}.getTypes();
2240888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.rawTypes()).has().exactly(
2257dd252788645e940eada959bdde927426e2531c9Paul Duffin        Class3.class, Interface3.class,
2267dd252788645e940eada959bdde927426e2531c9Paul Duffin        Iterable.class,
2277dd252788645e940eada959bdde927426e2531c9Paul Duffin        Class2.class,
2287dd252788645e940eada959bdde927426e2531c9Paul Duffin        Interface12.class,
2297dd252788645e940eada959bdde927426e2531c9Paul Duffin        Interface1.class,
2307dd252788645e940eada959bdde927426e2531c9Paul Duffin        Interface2.class,
2317dd252788645e940eada959bdde927426e2531c9Paul Duffin        Class1.class,
2327dd252788645e940eada959bdde927426e2531c9Paul Duffin        Object.class);
2330888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.interfaces().rawTypes()).has().exactly(
2347dd252788645e940eada959bdde927426e2531c9Paul Duffin        Interface3.class,
2357dd252788645e940eada959bdde927426e2531c9Paul Duffin        Interface12.class,
2367dd252788645e940eada959bdde927426e2531c9Paul Duffin        Interface1.class,
2377dd252788645e940eada959bdde927426e2531c9Paul Duffin        Interface2.class,
2387dd252788645e940eada959bdde927426e2531c9Paul Duffin        Iterable.class);
2390888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.classes().rawTypes()).has().exactly(
2407dd252788645e940eada959bdde927426e2531c9Paul Duffin        Class3.class,
2417dd252788645e940eada959bdde927426e2531c9Paul Duffin        Class2.class,
2427dd252788645e940eada959bdde927426e2531c9Paul Duffin        Class1.class,
2437dd252788645e940eada959bdde927426e2531c9Paul Duffin        Object.class);
2447dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeFirst(types);
2457dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2467dd252788645e940eada959bdde927426e2531c9Paul Duffin
2470888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public <A extends Class1 & Interface1, B extends A>
2480888a09821a98ac0680fad765217302858e70fa4Paul Duffin  void testGetTypes_ignoresTypeVariablesByDefault() {
2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin    TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes();
2500888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types).has().exactly(
2510888a09821a98ac0680fad765217302858e70fa4Paul Duffin        TypeToken.of(Interface1.class), TypeToken.of(Class1.class),
2520888a09821a98ac0680fad765217302858e70fa4Paul Duffin        TypeToken.of(Object.class));
2530888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertSubtypeFirst(types);
2540888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.interfaces())
2550888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(TypeToken.of(Interface1.class))
2560888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .inOrder();
2570888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.classes())
2580888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(TypeToken.of(Class1.class), TypeToken.of(Object.class))
2590888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .inOrder();
2600888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2610888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2620888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public <A extends Class1 & Interface1, B extends A>
2630888a09821a98ac0680fad765217302858e70fa4Paul Duffin  void testGetTypes_rawTypes_ignoresTypeVariablesByDefault() {
2640888a09821a98ac0680fad765217302858e70fa4Paul Duffin    TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes();
2650888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.rawTypes())
2660888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(Interface1.class, Class1.class, Object.class);
2670888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.interfaces().rawTypes())
2680888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(Interface1.class)
2690888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .inOrder();
2700888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.classes().rawTypes())
2710888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(Class1.class, Object.class)
2720888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .inOrder();
2730888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2740888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2757dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <A extends Interface1 & Interface2 & Interface3<String>>
2767dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetTypes_manyBounds() {
2770888a09821a98ac0680fad765217302858e70fa4Paul Duffin    TypeToken<?>.TypeSet types = TypeToken.of(new TypeCapture<A>() {}.capture()).getTypes();
2780888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(types.rawTypes())
2790888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(Interface1.class, Interface2.class, Interface3.class, Iterable.class);
2807dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2817dd252788645e940eada959bdde927426e2531c9Paul Duffin
2827dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void assertSubtypeFirst(TypeToken<?>.TypeSet types) {
2837dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeTokenBeforeSupertypeToken(types);
2847dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeTokenBeforeSupertypeToken(types.interfaces());
2857dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeTokenBeforeSupertypeToken(types.classes());
2867dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeBeforeSupertype(types.rawTypes());
2877dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeBeforeSupertype(types.interfaces().rawTypes());
2887dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeBeforeSupertype(types.classes().rawTypes());
2897dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2907dd252788645e940eada959bdde927426e2531c9Paul Duffin
2917dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void assertSubtypeTokenBeforeSupertypeToken(
2927dd252788645e940eada959bdde927426e2531c9Paul Duffin      Iterable<? extends TypeToken<?>> types) {
2937dd252788645e940eada959bdde927426e2531c9Paul Duffin    int i = 0;
2947dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (TypeToken<?> left : types) {
2957dd252788645e940eada959bdde927426e2531c9Paul Duffin      int j = 0;
2967dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (TypeToken<?> right : types) {
2977dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (left.isAssignableFrom(right)) {
2987dd252788645e940eada959bdde927426e2531c9Paul Duffin          assertTrue(left + " should be after " + right, i >= j);
2997dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
3007dd252788645e940eada959bdde927426e2531c9Paul Duffin        j++;
3017dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
3027dd252788645e940eada959bdde927426e2531c9Paul Duffin      i++;
3037dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3047dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3057dd252788645e940eada959bdde927426e2531c9Paul Duffin
3067dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void assertSubtypeBeforeSupertype(Iterable<? extends Class<?>> types) {
3077dd252788645e940eada959bdde927426e2531c9Paul Duffin    int i = 0;
3087dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (Class<?> left : types) {
3097dd252788645e940eada959bdde927426e2531c9Paul Duffin      int j = 0;
3107dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (Class<?> right : types) {
3117dd252788645e940eada959bdde927426e2531c9Paul Duffin        if (left.isAssignableFrom(right)) {
3127dd252788645e940eada959bdde927426e2531c9Paul Duffin          assertTrue(left + " should be after " + right, i >= j);
3137dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
3147dd252788645e940eada959bdde927426e2531c9Paul Duffin        j++;
3157dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
3167dd252788645e940eada959bdde927426e2531c9Paul Duffin      i++;
3177dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3187dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3197dd252788645e940eada959bdde927426e2531c9Paul Duffin
3207dd252788645e940eada959bdde927426e2531c9Paul Duffin  // Tests to make sure assertSubtypeBeforeSupertype() works.
3217dd252788645e940eada959bdde927426e2531c9Paul Duffin
3227dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeTokenBeforeSupertypeToken_empty() {
3237dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeTokenBeforeSupertypeToken(ImmutableList.<TypeToken<?>>of());
3247dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3257dd252788645e940eada959bdde927426e2531c9Paul Duffin
3267dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeTokenBeforeSupertypeToken_oneType() {
3277dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeTokenBeforeSupertypeToken(ImmutableList.of(TypeToken.of(String.class)));
3287dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3297dd252788645e940eada959bdde927426e2531c9Paul Duffin
3307dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeTokenBeforeSupertypeToken_subtypeFirst() {
3317dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeTokenBeforeSupertypeToken(
3327dd252788645e940eada959bdde927426e2531c9Paul Duffin        ImmutableList.of(TypeToken.of(String.class), TypeToken.of(CharSequence.class)));
3337dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3347dd252788645e940eada959bdde927426e2531c9Paul Duffin
3357dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeTokenBeforeSupertypeToken_supertypeFirst() {
3367dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
3377dd252788645e940eada959bdde927426e2531c9Paul Duffin      assertSubtypeTokenBeforeSupertypeToken(
3387dd252788645e940eada959bdde927426e2531c9Paul Duffin          ImmutableList.of(TypeToken.of(CharSequence.class), TypeToken.of(String.class)));
3397dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (AssertionError expected) {
3407dd252788645e940eada959bdde927426e2531c9Paul Duffin      return;
3417dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3427dd252788645e940eada959bdde927426e2531c9Paul Duffin    fail();
3437dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3447dd252788645e940eada959bdde927426e2531c9Paul Duffin
3457dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeTokenBeforeSupertypeToken_duplicate() {
3467dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
3477dd252788645e940eada959bdde927426e2531c9Paul Duffin      assertSubtypeTokenBeforeSupertypeToken(
3487dd252788645e940eada959bdde927426e2531c9Paul Duffin          ImmutableList.of(TypeToken.of(String.class), TypeToken.of(String.class)));
3497dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (AssertionError expected) {
3507dd252788645e940eada959bdde927426e2531c9Paul Duffin      return;
3517dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3527dd252788645e940eada959bdde927426e2531c9Paul Duffin    fail();
3537dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3547dd252788645e940eada959bdde927426e2531c9Paul Duffin
3557dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeBeforeSupertype_empty() {
3567dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeBeforeSupertype(ImmutableList.<Class<?>>of());
3577dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3587dd252788645e940eada959bdde927426e2531c9Paul Duffin
3597dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeBeforeSupertype_oneType() {
3607dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeBeforeSupertype(ImmutableList.of(String.class));
3617dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3627dd252788645e940eada959bdde927426e2531c9Paul Duffin
3637dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeBeforeSupertype_subtypeFirst() {
3647dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertSubtypeBeforeSupertype(
3657dd252788645e940eada959bdde927426e2531c9Paul Duffin        ImmutableList.of(String.class, CharSequence.class));
3667dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3677dd252788645e940eada959bdde927426e2531c9Paul Duffin
3687dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeBeforeSupertype_supertypeFirst() {
3697dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
3707dd252788645e940eada959bdde927426e2531c9Paul Duffin      assertSubtypeBeforeSupertype(
3717dd252788645e940eada959bdde927426e2531c9Paul Duffin          ImmutableList.of(CharSequence.class, String.class));
3727dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (AssertionError expected) {
3737dd252788645e940eada959bdde927426e2531c9Paul Duffin      return;
3747dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3757dd252788645e940eada959bdde927426e2531c9Paul Duffin    fail();
3767dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3777dd252788645e940eada959bdde927426e2531c9Paul Duffin
3787dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssertSubtypeBeforeSupertype_duplicate() {
3797dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
3807dd252788645e940eada959bdde927426e2531c9Paul Duffin      assertSubtypeBeforeSupertype(
3817dd252788645e940eada959bdde927426e2531c9Paul Duffin          ImmutableList.of(String.class, String.class));
3827dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (AssertionError expected) {
3837dd252788645e940eada959bdde927426e2531c9Paul Duffin      return;
3847dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
3857dd252788645e940eada959bdde927426e2531c9Paul Duffin    fail();
3867dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3877dd252788645e940eada959bdde927426e2531c9Paul Duffin
3887dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericSuperclass_noSuperclass() {
3897dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(new TypeToken<Object>() {}.getGenericSuperclass());
3907dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class),
3917dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Object[]>() {}.getGenericSuperclass());
3927dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(new TypeToken<List<String>>() {}.getGenericSuperclass());
3937dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class),
3947dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<String>[]>() {}.getGenericSuperclass());
3957dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3967dd252788645e940eada959bdde927426e2531c9Paul Duffin
3977dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericSuperclass_withSuperclass() {
3987dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<? super ArrayList<String>> superToken =
3997dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<ArrayList<String>>() {}.getGenericSuperclass();
4007dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(ArrayList.class.getSuperclass(), superToken.getRawType());
4017dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(String.class,
4027dd252788645e940eada959bdde927426e2531c9Paul Duffin        ((ParameterizedType) superToken.getType()).getActualTypeArguments()[0]);
4037dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Base.class), TypeToken.of(Sub.class).getGenericSuperclass());
4047dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class), TypeToken.of(Sub[].class).getGenericSuperclass());
4057dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4067dd252788645e940eada959bdde927426e2531c9Paul Duffin
4077dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testGetGenericSuperclass_typeVariable_unbounded() {
4087dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class),
4097dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericSuperclass());
4107dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
4117dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4127dd252788645e940eada959bdde927426e2531c9Paul Duffin
4137dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends ArrayList<String> & CharSequence>
4147dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericSuperclass_typeVariable_boundIsClass() {
4157dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<ArrayList<String>>() {},
4167dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericSuperclass());
4177dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
4187dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4197dd252788645e940eada959bdde927426e2531c9Paul Duffin
4207dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends Enum<T> & CharSequence>
4217dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericSuperclass_typeVariable_boundIsFBoundedClass() {
4227dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<Enum<T>>() {},
4237dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericSuperclass());
4247dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
4257dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4267dd252788645e940eada959bdde927426e2531c9Paul Duffin
4277dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends List<String> & CharSequence>
4287dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericSuperclass_typeVariable_boundIsInterface() {
4297dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericSuperclass());
4307dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
4317dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4327dd252788645e940eada959bdde927426e2531c9Paul Duffin
4337dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends ArrayList<String> & CharSequence, T1 extends T>
4347dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericSuperclass_typeVariable_boundIsTypeVariableAndClass() {
4357dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(new TypeCapture<T>() {}.capture()),
4367dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<T1>() {}.capture()).getGenericSuperclass());
4377dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class), new TypeToken<T[]>() {}.getGenericSuperclass());
4387dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4397dd252788645e940eada959bdde927426e2531c9Paul Duffin
4407dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends List<String> & CharSequence, T1 extends T>
4417dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericSuperclass_typeVariable_boundIsTypeVariableAndInterface() {
4427dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(TypeToken.of(new TypeCapture<T1>() {}.capture()).getGenericSuperclass());
4437dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class), new TypeToken<T1[]>() {}.getGenericSuperclass());
4447dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4457dd252788645e940eada959bdde927426e2531c9Paul Duffin
4467dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericSuperclass_wildcard_lowerBounded() {
4477dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class),
4487dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.supertypeOf(String.class)).getGenericSuperclass());
4497dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<Object>() {},
4507dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.supertypeOf(String[].class)).getGenericSuperclass());
4517dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<Object>() {},
4527dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.supertypeOf(CharSequence.class)).getGenericSuperclass());
4537dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4547dd252788645e940eada959bdde927426e2531c9Paul Duffin
4557dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericSuperclass_wildcard_boundIsClass() {
4567dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(Object.class),
4577dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.subtypeOf(Object.class)).getGenericSuperclass());
4587dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<Object[]>() {},
4597dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.subtypeOf(Object[].class)).getGenericSuperclass());
4607dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4617dd252788645e940eada959bdde927426e2531c9Paul Duffin
4627dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericSuperclass_wildcard_boundIsInterface() {
4637dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(TypeToken.of(Types.subtypeOf(CharSequence.class)).getGenericSuperclass());
4647dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<CharSequence[]>() {},
4657dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.subtypeOf(CharSequence[].class)).getGenericSuperclass());
4667dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4677dd252788645e940eada959bdde927426e2531c9Paul Duffin
4687dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testGetGenericInterfaces_typeVariable_unbounded() {
4690888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces()).isEmpty();
4707dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertHasArrayInterfaces(new TypeToken<T[]>() {});
4717dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4727dd252788645e940eada959bdde927426e2531c9Paul Duffin
4737dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends NoInterface> void testGetGenericInterfaces_typeVariable_boundIsClass() {
4740888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces()).isEmpty();
4757dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertHasArrayInterfaces(new TypeToken<T[]>() {});
4767dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4777dd252788645e940eada959bdde927426e2531c9Paul Duffin
4787dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends NoInterface&Iterable<String>>
4797dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericInterfaces_typeVariable_boundsAreClassWithInterface() {
4807dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertThat(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
4810888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(new TypeToken<Iterable<String>>() {});
4820888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasArrayInterfaces(new TypeToken<T[]>() {});
4830888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
4840888a09821a98ac0680fad765217302858e70fa4Paul Duffin
4850888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public <T extends CharSequence&Iterable<String>>
4860888a09821a98ac0680fad765217302858e70fa4Paul Duffin  void testGetGenericInterfaces_typeVariable_boundsAreInterfaces() {
4870888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertThat(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
4880888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<String>>() {});
4897dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertHasArrayInterfaces(new TypeToken<T[]>() {});
4907dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4917dd252788645e940eada959bdde927426e2531c9Paul Duffin
4927dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends CharSequence&Iterable<T>>
4937dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericInterfaces_typeVariable_boundsAreFBoundedInterfaces() {
4947dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertThat(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
4950888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(TypeToken.of(CharSequence.class), new TypeToken<Iterable<T>>() {});
4967dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertHasArrayInterfaces(new TypeToken<T[]>() {});
4977dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4987dd252788645e940eada959bdde927426e2531c9Paul Duffin
4997dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends Base&Iterable<T>>
5007dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericInterfaces_typeVariable_boundsAreClassWithFBoundedInterface() {
5017dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertThat(TypeToken.of(new TypeCapture<T>() {}.capture()).getGenericInterfaces())
5020888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(new TypeToken<Iterable<T>>() {});
5037dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertHasArrayInterfaces(new TypeToken<T[]>() {});
5047dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5057dd252788645e940eada959bdde927426e2531c9Paul Duffin
5067dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends NoInterface, T1 extends T, T2 extends T1>
5077dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericInterfaces_typeVariable_boundIsTypeVariableAndClass() {
5080888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(TypeToken.of(new TypeCapture<T2>() {}.capture()).getGenericInterfaces()).isEmpty();
5097dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertHasArrayInterfaces(new TypeToken<T2[]>() {});
5107dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5117dd252788645e940eada959bdde927426e2531c9Paul Duffin
5127dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends Iterable<T>, T1 extends T, T2 extends T1>
5137dd252788645e940eada959bdde927426e2531c9Paul Duffin  void testGetGenericInterfaces_typeVariable_boundIsTypeVariableAndInterface() {
5147dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertThat(TypeToken.of(new TypeCapture<T2>() {}.capture()).getGenericInterfaces())
5150888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(TypeToken.of(new TypeCapture<T1>() {}.capture()));
5167dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertHasArrayInterfaces(new TypeToken<T2[]>() {});
5177dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5187dd252788645e940eada959bdde927426e2531c9Paul Duffin
5197dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericInterfaces_wildcard_lowerBounded() {
5200888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(TypeToken.of(Types.supertypeOf(String.class)).getGenericInterfaces()).isEmpty();
5210888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(TypeToken.of(Types.supertypeOf(String[].class)).getGenericInterfaces()).isEmpty();
5227dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5237dd252788645e940eada959bdde927426e2531c9Paul Duffin
5247dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericInterfaces_wildcard_boundIsClass() {
5250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(TypeToken.of(Types.subtypeOf(Object.class)).getGenericInterfaces()).isEmpty();
5260888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(TypeToken.of(Types.subtypeOf(Object[].class)).getGenericInterfaces()).isEmpty();
5277dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5287dd252788645e940eada959bdde927426e2531c9Paul Duffin
5297dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericInterfaces_wildcard_boundIsInterface() {
5307dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Iterable<String>> interfaceType = new TypeToken<Iterable<String>>() {};
5317dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertThat(TypeToken.of(Types.subtypeOf(interfaceType.getType())).getGenericInterfaces())
5320888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactly(interfaceType);
5337dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertHasArrayInterfaces(new TypeToken<Iterable<String>[]>() {});
5347dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5357dd252788645e940eada959bdde927426e2531c9Paul Duffin
5367dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericInterfaces_noInterface() {
5370888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(new TypeToken<NoInterface>() {}.getGenericInterfaces()).isEmpty();
5387dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertHasArrayInterfaces(new TypeToken<NoInterface[]>() {});
5397dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5407dd252788645e940eada959bdde927426e2531c9Paul Duffin
5417dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetGenericInterfaces_withInterfaces() {
5427dd252788645e940eada959bdde927426e2531c9Paul Duffin    Map<Class<?>, Type> interfaceMap = Maps.newHashMap();
5437dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (TypeToken<?> interfaceType:
5447dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Implementation<Integer, String>>() {}.getGenericInterfaces()) {
5457dd252788645e940eada959bdde927426e2531c9Paul Duffin      interfaceMap.put(interfaceType.getRawType(), interfaceType.getType());
5467dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
5477dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(ImmutableMap.of(
5487dd252788645e940eada959bdde927426e2531c9Paul Duffin            Iterable.class, new TypeToken<Iterable<String>>() {}.getType(),
5497dd252788645e940eada959bdde927426e2531c9Paul Duffin            Map.class, new TypeToken<Map<Integer, String>>() {}.getType()),
5507dd252788645e940eada959bdde927426e2531c9Paul Duffin        interfaceMap);
5517dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5527dd252788645e940eada959bdde927426e2531c9Paul Duffin
5537dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface Interface1 {}
5547dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface Interface2 {}
5557dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface Interface3<T> extends Iterable<T> {}
5567dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface Interface12 extends Interface1, Interface2 {}
5577dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class Class1 implements Interface1 {}
5587dd252788645e940eada959bdde927426e2531c9Paul Duffin
5597dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static final class NoInterface {}
5607dd252788645e940eada959bdde927426e2531c9Paul Duffin
5617dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class Implementation<K, V>
5627dd252788645e940eada959bdde927426e2531c9Paul Duffin      implements Iterable<V>, Map<K, V> {}
5637dd252788645e940eada959bdde927426e2531c9Paul Duffin
5647dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class First<T> {}
5657dd252788645e940eada959bdde927426e2531c9Paul Duffin
5667dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class Second<D> extends First<D> {}
5677dd252788645e940eada959bdde927426e2531c9Paul Duffin
5687dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class Third<T, D> extends Second<T> {}
5697dd252788645e940eada959bdde927426e2531c9Paul Duffin
5707dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class Fourth<T, D> extends Third<D, T> {}
5717dd252788645e940eada959bdde927426e2531c9Paul Duffin
5727dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class ConcreteIS extends Fourth<Integer, String> {}
5737dd252788645e940eada959bdde927426e2531c9Paul Duffin
5747dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class ConcreteSI extends Fourth<String, Integer> {}
5757dd252788645e940eada959bdde927426e2531c9Paul Duffin
5767dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableClassToClass() {
5770888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @SuppressWarnings("rawtypes") // To test TypeToken<List>
5787dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List> tokL = new TypeToken<List>() {};
5797dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(List.class));
5807dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(ArrayList.class));
5817dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokL.isAssignableFrom(List[].class));
5827dd252788645e940eada959bdde927426e2531c9Paul Duffin
5837dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Number> tokN = new TypeToken<Number>() {};
5847dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokN.isAssignableFrom(Number.class));
5857dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokN.isAssignableFrom(Integer.class));
5867dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5877dd252788645e940eada959bdde927426e2531c9Paul Duffin
5887dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testAssignableParameterizedTypeToObject() {
5897dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Object.class).isAssignableFrom(
5907dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<T>() {}.capture())));
5917dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(TypeToken.of(int.class).isAssignableFrom(
5927dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<T>() {}.capture())));
5937dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
5947dd252788645e940eada959bdde927426e2531c9Paul Duffin
5957dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T, T1 extends T> void testAssignableGenericArrayToGenericArray() {
5967dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T[]>() {}));
5977dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T1[]>() {}));
5987dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(new TypeToken<T[]>() {}.isAssignableFrom(new TypeToken<T[][]>() {}));
5997dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6007dd252788645e940eada959bdde927426e2531c9Paul Duffin
6017dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableWildcardBoundedByArrayToArrayClass() throws Exception {
6027dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type wildcardType = Types.subtypeOf(Object[].class);
6037dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Object[].class).isAssignableFrom(wildcardType));
6047dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType));
6057dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType));
6067dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(TypeToken.of(int[].class).isAssignableFrom(wildcardType));
6077dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6087dd252788645e940eada959bdde927426e2531c9Paul Duffin
6097dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableArrayClassToBoundedWildcard() throws Exception {
6107dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> upperBounded = TypeToken.of(Types.subtypeOf(Object[].class));
6117dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class));
6127dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(upperBounded.isAssignableFrom(Object[].class));
6137dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(upperBounded.isAssignableFrom(Object[][].class));
6147dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(upperBounded.isAssignableFrom(String[].class));
6157dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(lowerBounded.isAssignableFrom(Object[].class));
6167dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(lowerBounded.isAssignableFrom(Object.class));
6177dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(lowerBounded.isAssignableFrom(Object[][].class));
6187dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(lowerBounded.isAssignableFrom(String[].class));
6197dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6207dd252788645e940eada959bdde927426e2531c9Paul Duffin
6217dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableWildcardBoundedByIntArrayToArrayClass() throws Exception {
6227dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type wildcardType = Types.subtypeOf(int[].class);
6237dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(int[].class).isAssignableFrom(wildcardType));
6247dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType));
6257dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType));
6267dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(TypeToken.of(Object[].class).isAssignableFrom(wildcardType));
6277dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6287dd252788645e940eada959bdde927426e2531c9Paul Duffin
6297dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableWildcardToWildcard() throws Exception {
6307dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> upperBounded = TypeToken.of(Types.subtypeOf(Object[].class));
6317dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class));
6327dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(lowerBounded.isAssignableFrom(upperBounded));
6337dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(lowerBounded.isAssignableFrom(lowerBounded));
6347dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(upperBounded.isAssignableFrom(upperBounded));
6357dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(upperBounded.isAssignableFrom(lowerBounded));
6367dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6377dd252788645e940eada959bdde927426e2531c9Paul Duffin
6387dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testAssignableGenericArrayToArrayClass() {
6397dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken<T[]>() {}));
6407dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken<T[][]>() {}));
6417dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Object[][].class).isAssignableFrom(new TypeToken<T[][]>() {}));
6427dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6437dd252788645e940eada959bdde927426e2531c9Paul Duffin
6447dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableParameterizedTypeToClass() {
6450888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @SuppressWarnings("rawtypes") // Trying to test raw class
6467dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List> tokL = new TypeToken<List>() {};
6477dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(StringList.class));
6487dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(
6497dd252788645e940eada959bdde927426e2531c9Paul Duffin        StringList.class.getGenericInterfaces()[0]));
6507dd252788645e940eada959bdde927426e2531c9Paul Duffin
6510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @SuppressWarnings("rawtypes") // Trying to test raw class
6527dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Second> tokS = new TypeToken<Second>() {};
6537dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokS.isAssignableFrom(Second.class));
6547dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokS.isAssignableFrom(Third.class.getGenericSuperclass()));
6557dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6567dd252788645e940eada959bdde927426e2531c9Paul Duffin
6577dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableArrayToClass() throws Exception {
6580888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @SuppressWarnings("rawtypes") // Trying to test raw class
6597dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List[]> tokL = new TypeToken<List[]>() {};
6607dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(List[].class));
6617dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokL.isAssignableFrom(List.class));
6627dd252788645e940eada959bdde927426e2531c9Paul Duffin
6630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @SuppressWarnings("rawtypes") // Trying to test raw class
6647dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Second[]> tokS = new TypeToken<Second[]>() {};
6657dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokS.isAssignableFrom(Second[].class));
6667dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokS.isAssignableFrom(Third[].class));
6677dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6687dd252788645e940eada959bdde927426e2531c9Paul Duffin
6690888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("rawtypes") // Trying to test raw class
6707dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableTokenToClass() {
6717dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List> tokL = new TypeToken<List>() {};
6727dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(new TypeToken<List>() {}));
6737dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(new TypeToken<List<String>>() {}));
6747dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(new TypeToken<List<?>>() {}));
6757dd252788645e940eada959bdde927426e2531c9Paul Duffin
6767dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Second> tokS = new TypeToken<Second>() {};
6777dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokS.isAssignableFrom(new TypeToken<Second>() {}));
6787dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokS.isAssignableFrom(new TypeToken<Third>() {}));
6797dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokS.isAssignableFrom(
6807dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Third<String, Integer>>() {}));
6817dd252788645e940eada959bdde927426e2531c9Paul Duffin
6827dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List[]> tokA = new TypeToken<List[]>() {};
6837dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokA.isAssignableFrom(new TypeToken<List[]>() {}));
6847dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokA.isAssignableFrom(new TypeToken<List<String>[]>() {}));
6857dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokA.isAssignableFrom(new TypeToken<List<?>[]>() {}));
6867dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6877dd252788645e940eada959bdde927426e2531c9Paul Duffin
6887dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableClassToType() {
6897dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
6907dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenL.isAssignableFrom(StringList.class));
6917dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokenL.isAssignableFrom(List.class));
6927dd252788645e940eada959bdde927426e2531c9Paul Duffin
6937dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
6947dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenF.isAssignableFrom(ConcreteIS.class));
6957dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokenF.isAssignableFrom(ConcreteSI.class));
6967dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
6977dd252788645e940eada959bdde927426e2531c9Paul Duffin
6987dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableClassToArrayType() {
6997dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>[]> tokenL = new TypeToken<List<String>[]>() {};
7007dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenL.isAssignableFrom(StringList[].class));
7017dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokenL.isAssignableFrom(List[].class));
7027dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
7037dd252788645e940eada959bdde927426e2531c9Paul Duffin
7047dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableParameterizedTypeToType() {
7057dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
7067dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenL.isAssignableFrom(
7077dd252788645e940eada959bdde927426e2531c9Paul Duffin        StringList.class.getGenericInterfaces()[0]));
7087dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokenL.isAssignableFrom(
7097dd252788645e940eada959bdde927426e2531c9Paul Duffin        IntegerList.class.getGenericInterfaces()[0]));
7107dd252788645e940eada959bdde927426e2531c9Paul Duffin
7117dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
7127dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenF.isAssignableFrom(
7137dd252788645e940eada959bdde927426e2531c9Paul Duffin        ConcreteIS.class.getGenericSuperclass()));
7147dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokenF.isAssignableFrom(
7157dd252788645e940eada959bdde927426e2531c9Paul Duffin        ConcreteSI.class.getGenericSuperclass()));
7167dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
7177dd252788645e940eada959bdde927426e2531c9Paul Duffin
7187dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGenericArrayTypeToArrayType() throws Exception {
7197dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>[]> tokL = new TypeToken<List<String>[]>() {};
7207dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<ArrayList<String>[]> token =
7217dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<ArrayList<String>[]>() {};
7227dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(tokL.getType()));
7237dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokL.isAssignableFrom(token.getType()));
7247dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
7257dd252788645e940eada959bdde927426e2531c9Paul Duffin
7267dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableTokenToType() {
7277dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<String>> tokenL = new TypeToken<List<String>>() {};
7287dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenL.isAssignableFrom(new TypeToken<List<String>>() {}));
7297dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenL.isAssignableFrom(new TypeToken<ArrayList<String>>() {}));
7307dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenL.isAssignableFrom(new TypeToken<StringList>() {}));
7317dd252788645e940eada959bdde927426e2531c9Paul Duffin
7327dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<First<String>> tokenF = new TypeToken<First<String>>() {};
7337dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenF.isAssignableFrom(new TypeToken<Second<String>>() {}));
7347dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenF.isAssignableFrom(
7357dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Third<String, Integer>>() {}));
7367dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokenF.isAssignableFrom(
7377dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Third<Integer, String>>() {}));
7387dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenF.isAssignableFrom(
7397dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Fourth<Integer, String>>() {}));
7407dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokenF.isAssignableFrom(
7417dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Fourth<String, Integer>>() {}));
7427dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(tokenF.isAssignableFrom(new TypeToken<ConcreteIS>() {}));
7437dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(tokenF.isAssignableFrom(new TypeToken<ConcreteSI>() {}));
7447dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
7457dd252788645e940eada959bdde927426e2531c9Paul Duffin
7467dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testAssignableWithWildcards() {
7477dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> unboundedToken = new TypeToken<List<?>>() {};
7487dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> upperBoundToken = new TypeToken<List<? extends Number>>() {};
7497dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> lowerBoundToken = new TypeToken<List<? super Number>>() {};
7507dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> concreteToken = new TypeToken<List<Number>>() {};
7517dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> subtypeToken = new TypeToken<List<Integer>>() {};
7527dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> supertypeToken = new TypeToken<List<Serializable>>() {};
7537dd252788645e940eada959bdde927426e2531c9Paul Duffin    List<TypeToken<?>> allTokens = ImmutableList.of(
7547dd252788645e940eada959bdde927426e2531c9Paul Duffin        unboundedToken, upperBoundToken, lowerBoundToken,
7557dd252788645e940eada959bdde927426e2531c9Paul Duffin        concreteToken, subtypeToken, supertypeToken);
7567dd252788645e940eada959bdde927426e2531c9Paul Duffin
7577dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (TypeToken<?> typeToken : allTokens) {
7587dd252788645e940eada959bdde927426e2531c9Paul Duffin      assertTrue(typeToken.toString(), unboundedToken.isAssignableFrom(typeToken));
7597dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
7607dd252788645e940eada959bdde927426e2531c9Paul Duffin
7617dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(upperBoundToken.isAssignableFrom(unboundedToken));
7627dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(upperBoundToken.isAssignableFrom(upperBoundToken));
7637dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(upperBoundToken.isAssignableFrom(lowerBoundToken));
7647dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(upperBoundToken.isAssignableFrom(concreteToken));
7657dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(upperBoundToken.isAssignableFrom(subtypeToken));
7667dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(upperBoundToken.isAssignableFrom(supertypeToken));
7677dd252788645e940eada959bdde927426e2531c9Paul Duffin
7687dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(lowerBoundToken.isAssignableFrom(unboundedToken));
7697dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(lowerBoundToken.isAssignableFrom(upperBoundToken));
7707dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(lowerBoundToken.isAssignableFrom(lowerBoundToken));
7717dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(lowerBoundToken.isAssignableFrom(concreteToken));
7727dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(lowerBoundToken.isAssignableFrom(subtypeToken));
7737dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(lowerBoundToken.isAssignableFrom(supertypeToken));
7747dd252788645e940eada959bdde927426e2531c9Paul Duffin
7757dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (TypeToken<?> typeToken : allTokens) {
7767dd252788645e940eada959bdde927426e2531c9Paul Duffin      assertEquals(typeToken.toString(),
7777dd252788645e940eada959bdde927426e2531c9Paul Duffin          typeToken == concreteToken, concreteToken.isAssignableFrom(typeToken));
7787dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
7797dd252788645e940eada959bdde927426e2531c9Paul Duffin
7807dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (TypeToken<?> typeToken : allTokens) {
7817dd252788645e940eada959bdde927426e2531c9Paul Duffin      assertEquals(typeToken.toString(),
7827dd252788645e940eada959bdde927426e2531c9Paul Duffin          typeToken == subtypeToken, subtypeToken.isAssignableFrom(typeToken));
7837dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
7847dd252788645e940eada959bdde927426e2531c9Paul Duffin
7857dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (TypeToken<?> typeToken : allTokens) {
7867dd252788645e940eada959bdde927426e2531c9Paul Duffin      assertEquals(typeToken.toString(),
7877dd252788645e940eada959bdde927426e2531c9Paul Duffin          typeToken == supertypeToken, supertypeToken.isAssignableFrom(typeToken));
7887dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
7897dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
7907dd252788645e940eada959bdde927426e2531c9Paul Duffin
7917dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <N1 extends Number, N2 extends Number, N11 extends N1>
7927dd252788645e940eada959bdde927426e2531c9Paul Duffin      void testIsAssignableFrom_typeVariable() {
7937dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(TypeToken.of(new TypeCapture<N1>() {}.capture()),
7947dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<N1>() {}.capture()));
7957dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNotAssignable(new TypeToken<List<N11>>() {},
7967dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<N1>>() {});
7977dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNotAssignable(new TypeToken<Number>() {},
7987dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<N1>() {}.capture()));
7997dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(TypeToken.of(new TypeCapture<N11>() {}.capture()),
8007dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<N1>() {}.capture()));
8017dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNotAssignable(TypeToken.of(new TypeCapture<N2>() {}.capture()),
8027dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<N1>() {}.capture()));
8037dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
8047dd252788645e940eada959bdde927426e2531c9Paul Duffin
8057dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <N1 extends Number, N2 extends Number, N11 extends N1>
8067dd252788645e940eada959bdde927426e2531c9Paul Duffin      void testIsAssignableFrom_equalWildcardTypes() {
8077dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<? extends N1>>() {},
8087dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends N1>>() {});
8097dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<? super N1>>() {},
8107dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super N1>>() {});
8117dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<? extends Number>>() {},
8127dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends Number>>() {});
8137dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<? super Number>>() {},
8147dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super Number>>() {});
8157dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
8167dd252788645e940eada959bdde927426e2531c9Paul Duffin
8177dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <N> void testIsAssignableFrom_wildcard_noBound() {
8187dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<? super N>>() {},
8197dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<?>>() {});
8207dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<N>>() {},
8217dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<?>>() {});
8227dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
8237dd252788645e940eada959bdde927426e2531c9Paul Duffin
8247dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <N1 extends Number, N2 extends Number, N11 extends N1>
8257dd252788645e940eada959bdde927426e2531c9Paul Duffin      void testIsAssignableFrom_wildcardType_upperBoundMatch() {
8267dd252788645e940eada959bdde927426e2531c9Paul Duffin    // ? extends T
8277dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<N11>>() {},
8287dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends N1>>() {});
8297dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNotAssignable(new TypeToken<List<N1>>() {},
8307dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends N11>>() {});
8317dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNotAssignable(new TypeToken<List<Number>>() {},
8327dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends N11>>() {});
8337dd252788645e940eada959bdde927426e2531c9Paul Duffin
8347dd252788645e940eada959bdde927426e2531c9Paul Duffin    // ? extends Number
8357dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<N1>>() {},
8367dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends Number>>() {});
8377dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<ArrayList<N1>>() {},
8387dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends Number>>() {});
8397dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<? extends N11>>() {},
8407dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends Number>>() {});
8417dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
8427dd252788645e940eada959bdde927426e2531c9Paul Duffin
8437dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <N1 extends Number, N2 extends Number, N11 extends N1>
8447dd252788645e940eada959bdde927426e2531c9Paul Duffin      void testIsAssignableFrom_wildcardType_lowerBoundMatch() {
8457dd252788645e940eada959bdde927426e2531c9Paul Duffin    // ? super T
8467dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<N1>>() {},
8477dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super N11>>() {});
8487dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<ArrayList<Number>>() {},
8497dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super N1>>() {});
8507dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNotAssignable(new TypeToken<ArrayList<? super N11>>() {},
8517dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super Number>>() {});
8527dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<ArrayList<? super N1>>() {},
8537dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super N11>>() {});
8547dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<ArrayList<? super Number>>() {},
8557dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super N11>>() {});
8567dd252788645e940eada959bdde927426e2531c9Paul Duffin
8577dd252788645e940eada959bdde927426e2531c9Paul Duffin    // ? super Number
8587dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNotAssignable(new TypeToken<ArrayList<N11>>() {},
8597dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super Number>>() {});
8607dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<ArrayList<Number>>() {},
8617dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super Number>>() {});
8627dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<ArrayList<Object>>() {},
8637dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? super Number>>() {});
8647dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
8657dd252788645e940eada959bdde927426e2531c9Paul Duffin
8667dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <L extends List<R>, R extends List<L>>
8677dd252788645e940eada959bdde927426e2531c9Paul Duffin      void testIsAssignableFrom_recursiveTypeVariableBounds() {
8687dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(TypeToken.of(new TypeCapture<L>() {}.capture()),
8697dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<L>() {}.capture()));
8707dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNotAssignable(TypeToken.of(new TypeCapture<R>() {}.capture()),
8717dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(new TypeCapture<L>() {}.capture()));
8727dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(TypeToken.of(new TypeCapture<L>() {}.capture()),
8737dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<R>>() {});
8747dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
8757dd252788645e940eada959bdde927426e2531c9Paul Duffin
8767dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testIsAssignableFrom_resolved() {
8777dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(Assignability.of().isAssignable());
8787dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(new Assignability<Integer, Integer>() {}.isAssignable());
8797dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(new Assignability<Integer, Object>() {}.isAssignable());
8807dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(new Assignability<Integer, String>() {}.isAssignable());
8817dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeTokenTest.<Number, Integer>assignabilityTestWithTypeVariables();
8827dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
8837dd252788645e940eada959bdde927426e2531c9Paul Duffin
8847dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static <N1 extends Number, N11 extends N1>
8857dd252788645e940eada959bdde927426e2531c9Paul Duffin      void assignabilityTestWithTypeVariables() {
8867dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(new Assignability<N11, N1>() {}.isAssignable());
8877dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(new Assignability<N11, Number>() {}.isAssignable());
8887dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(new Assignability<Number, N11>() {}.isAssignable());
8897dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
8907dd252788645e940eada959bdde927426e2531c9Paul Duffin
8917dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testIsArray_arrayClasses() {
8927dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Object[].class).isArray());
8937dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Object[][].class).isArray());
8947dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(char[].class).isArray());
8957dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(char[][].class).isArray());
8967dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(byte[].class).isArray());
8977dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(short[].class).isArray());
8987dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(int[].class).isArray());
8997dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(long[].class).isArray());
9007dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(float[].class).isArray());
9017dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(double[].class).isArray());
9027dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(TypeToken.of(Object.class).isArray());
9037dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(TypeToken.of(void.class).isArray());
9047dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
9057dd252788645e940eada959bdde927426e2531c9Paul Duffin
9067dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testIsArray_genericArrayClasses() {
9077dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(TypeToken.of(new TypeCapture<T>() {}.capture()).isArray());
9087dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(new TypeToken<T[]>() {}.isArray());
9097dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(new TypeToken<T[][]>() {}.isArray());
9107dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
9117dd252788645e940eada959bdde927426e2531c9Paul Duffin
9127dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testIsArray_wildcardType() throws Exception {
9137dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Types.subtypeOf(Object[].class)).isArray());
9147dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(TypeToken.of(Types.subtypeOf(int[].class)).isArray());
9157dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(TypeToken.of(Types.subtypeOf(Object.class)).isArray());
9167dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(TypeToken.of(Types.supertypeOf(Object[].class)).isArray());
9177dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
9187dd252788645e940eada959bdde927426e2531c9Paul Duffin
9190888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public <T extends Integer> void testPrimitiveWrappingAndUnwrapping() {
9200888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (Class<?> type : Primitives.allPrimitiveTypes()) {
9210888a09821a98ac0680fad765217302858e70fa4Paul Duffin      assertIsPrimitive(TypeToken.of(type));
9220888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
9230888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (Class<?> type : Primitives.allWrapperTypes()) {
9240888a09821a98ac0680fad765217302858e70fa4Paul Duffin      assertIsWrapper(TypeToken.of(type));
9250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
9260888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNotPrimitiveNorWrapper(TypeToken.of(String.class));
9270888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNotPrimitiveNorWrapper(TypeToken.of(Object[].class));
9280888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNotPrimitiveNorWrapper(TypeToken.of(Types.subtypeOf(Object.class)));
9290888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNotPrimitiveNorWrapper(new TypeToken<List<String>>() {});
9300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNotPrimitiveNorWrapper(TypeToken.of(new TypeCapture<T>() {}.capture()));
9310888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
9320888a09821a98ac0680fad765217302858e70fa4Paul Duffin
9337dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetComponentType_arrayClasses() {
9347dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Object.class, TypeToken.of(Object[].class).getComponentType().getType());
9357dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Object[].class, TypeToken.of(Object[][].class).getComponentType().getType());
9367dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(char.class, TypeToken.of(char[].class).getComponentType().getType());
9377dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(char[].class, TypeToken.of(char[][].class).getComponentType().getType());
9387dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(byte.class, TypeToken.of(byte[].class).getComponentType().getType());
9397dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(short.class, TypeToken.of(short[].class).getComponentType().getType());
9407dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(int.class, TypeToken.of(int[].class).getComponentType().getType());
9417dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(long.class, TypeToken.of(long[].class).getComponentType().getType());
9427dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(float.class, TypeToken.of(float[].class).getComponentType().getType());
9437dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(double.class, TypeToken.of(double[].class).getComponentType().getType());
9447dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(TypeToken.of(Object.class).getComponentType());
9457dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(TypeToken.of(void.class).getComponentType());
9467dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
9477dd252788645e940eada959bdde927426e2531c9Paul Duffin
9487dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testGetComponentType_genericArrayClasses() {
9497dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(TypeToken.of(new TypeCapture<T>() {}.capture()).getComponentType());
9507dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(new TypeCapture<T>() {}.capture()),
9517dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<T[]>() {}.getComponentType());
9527dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<T[]>() {}, new TypeToken<T[][]>() {}.getComponentType());
9537dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
9547dd252788645e940eada959bdde927426e2531c9Paul Duffin
9557dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetComponentType_wildcardType() throws Exception {
9567dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Types.subtypeOf(Object.class),
9577dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.subtypeOf(Object[].class)).getComponentType().getType());
9587dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Types.subtypeOf(Object[].class),
9597dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.newArrayType(
9607dd252788645e940eada959bdde927426e2531c9Paul Duffin            TypeToken.of(Types.subtypeOf(Object[].class)).getComponentType().getType()));
9617dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(int.class,
9627dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.subtypeOf(int[].class)).getComponentType().getType());
9637dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(TypeToken.of(Types.subtypeOf(Object.class)).getComponentType());
9647dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertNull(TypeToken.of(Types.supertypeOf(Object[].class)).getComponentType());
9657dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
9667dd252788645e940eada959bdde927426e2531c9Paul Duffin
9677dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface NumberList<T extends Number> {}
9687dd252788645e940eada959bdde927426e2531c9Paul Duffin
9697dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testImplicitUpperBoundForWildcards() {
9707dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(
9717dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<NumberList<? extends Number>>() {},
9727dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<NumberList<?>>() {});
9737dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(
9747dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<NumberList<? super Integer>>() {},
9757dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<NumberList<?>>() {});
9767dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
9777dd252788645e940eada959bdde927426e2531c9Paul Duffin
9787dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends Readable & Appendable> void testMultiBound() {
9797dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<T>>() {},
9807dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends Readable>>() {});
9817dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertAssignable(new TypeToken<List<T>>() {},
9827dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<? extends Appendable>>() {});
9837dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
9847dd252788645e940eada959bdde927426e2531c9Paul Duffin
9857dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testToGenericType() {
9867dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(String.class), TypeToken.toGenericType(String.class));
9877dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<int[]>() {}, TypeToken.toGenericType(int[].class));
9880888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @SuppressWarnings("rawtypes") // Iterable.class
9897dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<? extends Iterable> genericType = TypeToken.toGenericType(Iterable.class);
9907dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Iterable.class, genericType.getRawType());
9917dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Types.newParameterizedType(Iterable.class, Iterable.class.getTypeParameters()[0]),
9927dd252788645e940eada959bdde927426e2531c9Paul Duffin        genericType.getType());
9937dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
9947dd252788645e940eada959bdde927426e2531c9Paul Duffin
9957dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface ListIterable<T> extends Iterable<List<T>> {}
9967dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface StringListIterable extends ListIterable<String> {}
9977dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface ListArrayIterable<T> extends Iterable<List<T>[]> {}
9987dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface StringListArrayIterable extends ListIterable<String> {}
9997dd252788645e940eada959bdde927426e2531c9Paul Duffin
10007dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_withTypeVariable() {
10017dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType expectedType = Types.newParameterizedType(Iterable.class,
10027dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.newParameterizedType(List.class, ListIterable.class.getTypeParameters()[0]));
10037dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(expectedType,
10047dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(ListIterable.class).getSupertype(Iterable.class).getType());
10057dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10067dd252788645e940eada959bdde927426e2531c9Paul Duffin
10077dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_withoutTypeVariable() {
10087dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType expectedType = Types.newParameterizedType(Iterable.class,
10097dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.newParameterizedType(List.class, String.class));
10107dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(expectedType,
10117dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(StringListIterable.class).getSupertype(Iterable.class).getType());
10127dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10137dd252788645e940eada959bdde927426e2531c9Paul Duffin
10147dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_chained() {
10157dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unchecked") // StringListIterable extensd ListIterable<String>
10167dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<ListIterable<String>> listIterableType = (TypeToken<ListIterable<String>>)
10177dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(StringListIterable.class).getSupertype(ListIterable.class);
10187dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType expectedType = Types.newParameterizedType(Iterable.class,
10197dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.newParameterizedType(List.class, String.class));
10207dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(expectedType, listIterableType.getSupertype(Iterable.class).getType());
10217dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10227dd252788645e940eada959bdde927426e2531c9Paul Duffin
10237dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_withArray() {
10247dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<Iterable<List<String>>[]>() {},
10257dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(StringListIterable[].class).getSupertype(Iterable[].class));
10267dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(int[].class, TypeToken.of(int[].class).getSupertype(int[].class).getType());
10277dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Object.class, TypeToken.of(int[].class).getSupertype(Object.class).getType());
10287dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(int[][].class, TypeToken.of(int[][].class).getSupertype(int[][].class).getType());
10297dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Object[].class,
10307dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(String[].class).getSupertype(Object[].class).getType());
10317dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Object.class, TypeToken.of(String[].class).getSupertype(Object.class).getType());
10327dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10337dd252788645e940eada959bdde927426e2531c9Paul Duffin
10347dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_fromWildcard() {
10357dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unchecked") // can't do new TypeToken<? extends ...>() {}
10367dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<? extends List<String>> type = (TypeToken<? extends List<String>>)
10377dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.subtypeOf(new TypeToken<List<String>>() {}.getType()));
10387dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<Iterable<String>>() {}, type.getSupertype(Iterable.class));
10397dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10407dd252788645e940eada959bdde927426e2531c9Paul Duffin
10417dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends Iterable<String>> void testGetSupertype_fromTypeVariable() {
10427dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unchecked") // to construct TypeToken<T> from TypeToken.of()
10437dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<T> typeVariableToken = (TypeToken<T>) TypeToken.of(new TypeCapture<T>() {}.capture());
10447dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<Iterable<String>>() {},
10457dd252788645e940eada959bdde927426e2531c9Paul Duffin        typeVariableToken.getSupertype(Iterable.class));
10467dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10477dd252788645e940eada959bdde927426e2531c9Paul Duffin
10487dd252788645e940eada959bdde927426e2531c9Paul Duffin  @SuppressWarnings("rawtypes") // purpose is to test raw type
10497dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_fromRawClass() {
10507dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Types.newParameterizedType(Iterable.class, List.class.getTypeParameters()[0]),
10517dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List>() {}.getSupertype(Iterable.class).getType());
10527dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10537dd252788645e940eada959bdde927426e2531c9Paul Duffin
10540888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings({"rawtypes", "unchecked"}) // purpose is to test raw type
10557dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_notSupertype() {
10567dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
10577dd252788645e940eada959bdde927426e2531c9Paul Duffin      new TypeToken<List<String>>() {}.getSupertype((Class) String.class);
10587dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
10597dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
10607dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10617dd252788645e940eada959bdde927426e2531c9Paul Duffin
10627dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_fromArray() {
10637dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<Iterable<String>[]>() {},
10647dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<String>[]>() {}.getSupertype(Iterable[].class));
10657dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10667dd252788645e940eada959bdde927426e2531c9Paul Duffin
10677dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface ListMap<K, V> extends Map<K, List<V>> {}
10687dd252788645e940eada959bdde927426e2531c9Paul Duffin
10697dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_fullyGenericType() {
10707dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType expectedType = Types.newParameterizedType(Map.class,
10717dd252788645e940eada959bdde927426e2531c9Paul Duffin        ListMap.class.getTypeParameters()[0],
10727dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.newParameterizedType(List.class, ListMap.class.getTypeParameters()[1]));
10737dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(expectedType,
10747dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(ListMap.class).getSupertype(Map.class).getType());
10757dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10767dd252788645e940eada959bdde927426e2531c9Paul Duffin
10777dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSupertype_fullySpecializedType() {
10787dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type expectedType = new TypeToken<Map<String, List<Object>>>() {}.getType();
10797dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(expectedType,
10807dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<ListMap<String, Object>>() {}.getSupertype(Map.class).getType());
10817dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10827dd252788645e940eada959bdde927426e2531c9Paul Duffin
10837dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface StringListMap<V> extends ListMap<String, V> {}
10847dd252788645e940eada959bdde927426e2531c9Paul Duffin
10857dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <V> void testGetSupertype_partiallySpecializedType() {
10867dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type expectedType = new TypeToken<Map<String, List<V>>>() {}.getType();
10877dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(expectedType,
10887dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<StringListMap<V>>() {}.getSupertype(Map.class).getType());
10897dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10907dd252788645e940eada959bdde927426e2531c9Paul Duffin
10917dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSubtype_withTypeVariable() {
10927dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<ListIterable<String>>() {},
10937dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Iterable<List<String>>>() {}.getSubtype(ListIterable.class));
10947dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<ListArrayIterable<String>>() {},
10957dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Iterable<List<String>[]>>() {}.getSubtype(ListArrayIterable.class));
10967dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<ListArrayIterable<String>[]>() {},
10977dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Iterable<List<String>[]>[]>() {}.getSubtype(ListArrayIterable[].class));
10987dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
10997dd252788645e940eada959bdde927426e2531c9Paul Duffin
11007dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSubtype_withoutTypeVariable() {
11017dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(StringListIterable.class,
11027dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Iterable.class).getSubtype(StringListIterable.class).getType());
11037dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(StringListIterable[].class,
11047dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Iterable[].class).getSubtype(StringListIterable[].class).getType());
11057dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(StringListArrayIterable.class),
11067dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Iterable<List<String>>>() {}.getSubtype(StringListArrayIterable.class));
11077dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(StringListArrayIterable[].class),
11087dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Iterable<List<String>>[]>() {}.getSubtype(StringListArrayIterable[].class));
11097dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11107dd252788645e940eada959bdde927426e2531c9Paul Duffin
11117dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSubtype_withArray() {
11127dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(StringListIterable[].class),
11137dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Iterable[].class).getSubtype(StringListIterable[].class));
11147dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(String[].class),
11157dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Object[].class).getSubtype(String[].class));
11167dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(int[].class),
11177dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Object.class).getSubtype(int[].class));
11187dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11197dd252788645e940eada959bdde927426e2531c9Paul Duffin
11207dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSubtype_fromWildcard() {
11217dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unchecked") // can't do new TypeToken<? extends ...>() {}
11227dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<? super Iterable<String>> type = (TypeToken<? super Iterable<String>>)
11237dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.supertypeOf(new TypeToken<Iterable<String>>() {}.getType()));
11247dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<List<String>>() {}, type.getSubtype(List.class));
11257dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11267dd252788645e940eada959bdde927426e2531c9Paul Duffin
11277dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSubtype_fromWildcard_lowerBoundNotSupertype() {
11287dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unchecked") // can't do new TypeToken<? extends ...>() {}
11297dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<? super Iterable<String>> type = (TypeToken<? super Iterable<String>>)
11307dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.supertypeOf(new TypeToken<ImmutableList<String>>() {}.getType()));
11317dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
11327dd252788645e940eada959bdde927426e2531c9Paul Duffin      type.getSubtype(List.class);
11337dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
11347dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
11357dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11367dd252788645e940eada959bdde927426e2531c9Paul Duffin
11377dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSubtype_fromWildcard_upperBounded() {
11387dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unchecked") // can't do new TypeToken<? extends ...>() {}
11397dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<? extends Iterable<String>> type = (TypeToken<? extends Iterable<String>>)
11407dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(Types.subtypeOf(new TypeToken<Iterable<String>>() {}.getType()));
11417dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
11427dd252788645e940eada959bdde927426e2531c9Paul Duffin      type.getSubtype(Iterable.class);
11437dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
11447dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
11457dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11467dd252788645e940eada959bdde927426e2531c9Paul Duffin
11477dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends Iterable<String>> void testGetSubtype_fromTypeVariable() {
11487dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
11497dd252788645e940eada959bdde927426e2531c9Paul Duffin      TypeToken.of(new TypeCapture<T>() {}.capture()).getSubtype(List.class);
11507dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
11517dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
11527dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11537dd252788645e940eada959bdde927426e2531c9Paul Duffin
11547dd252788645e940eada959bdde927426e2531c9Paul Duffin  @SuppressWarnings("rawtypes") // purpose is to test raw type
11557dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSubtype_fromRawClass() {
11567dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(List.class, new TypeToken<Iterable>() {}.getSubtype(List.class).getType());
11577dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11587dd252788645e940eada959bdde927426e2531c9Paul Duffin
11597dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testGetSubtype_fromArray() {
11607dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<List<String>[]>() {},
11617dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Iterable<String>[]>() {}.getSubtype(List[].class));
11627dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11637dd252788645e940eada959bdde927426e2531c9Paul Duffin
11647dd252788645e940eada959bdde927426e2531c9Paul Duffin  @SuppressWarnings("unchecked") // To construct TypeToken<T> with TypeToken.of()
11657dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testWhere_circleRejected() {
11667dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<List<T>> type = new TypeToken<List<T>>() {};
11677dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
11687dd252788645e940eada959bdde927426e2531c9Paul Duffin      type.where(new TypeParameter<T>() {},
11697dd252788645e940eada959bdde927426e2531c9Paul Duffin          (TypeToken<T>) TypeToken.of(new TypeCapture<T>() {}.capture()));
11707dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
11717dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
11727dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11737dd252788645e940eada959bdde927426e2531c9Paul Duffin
11747dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testWhere() {
11757dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(
11767dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Map<String, Integer>>() {},
11777dd252788645e940eada959bdde927426e2531c9Paul Duffin        mapOf(String.class, Integer.class));
11787dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<int[]>() {}, arrayOf(int.class));
11797dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(int[].class, arrayOf(int.class).getRawType());
11807dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11817dd252788645e940eada959bdde927426e2531c9Paul Duffin
11827dd252788645e940eada959bdde927426e2531c9Paul Duffin  @SuppressWarnings("unused") // used by reflection
11837dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class Holder<T> {
11847dd252788645e940eada959bdde927426e2531c9Paul Duffin    T element;
11857dd252788645e940eada959bdde927426e2531c9Paul Duffin    List<T> list;
11867dd252788645e940eada959bdde927426e2531c9Paul Duffin    List<T>[] matrix;
11877dd252788645e940eada959bdde927426e2531c9Paul Duffin
11887dd252788645e940eada959bdde927426e2531c9Paul Duffin    void setList(List<T> list) {
11897dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.list = list;
11907dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
11917dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
11927dd252788645e940eada959bdde927426e2531c9Paul Duffin
11937dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testWildcardCaptured_methodParameter_upperBound() throws Exception {
11947dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Holder<?>> type = new TypeToken<Holder<?>>() {};
11957dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> parameterType = type.resolveType(
11967dd252788645e940eada959bdde927426e2531c9Paul Duffin        Holder.class.getDeclaredMethod("setList", List.class).getGenericParameterTypes()[0]);
11977dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(List.class, parameterType.getRawType());
11987dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(parameterType.getType().toString(),
11997dd252788645e940eada959bdde927426e2531c9Paul Duffin        parameterType.isAssignableFrom(new TypeToken<List<Integer>>() {}));
12007dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12017dd252788645e940eada959bdde927426e2531c9Paul Duffin
12027dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testWildcardCaptured_field_upperBound() throws Exception {
12037dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Holder<?>> type = new TypeToken<Holder<?>>() {};
12047dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<?> matrixType = type.resolveType(
12057dd252788645e940eada959bdde927426e2531c9Paul Duffin        Holder.class.getDeclaredField("matrix").getGenericType());
12067dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(List[].class, matrixType.getRawType());
12070888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(matrixType.getType())
12087dd252788645e940eada959bdde927426e2531c9Paul Duffin        .isNotEqualTo(new TypeToken<List<?>[]>() {}.getType());
12097dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12107dd252788645e940eada959bdde927426e2531c9Paul Duffin
12117dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testArrayClassPreserved() {
12127dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(int[].class, TypeToken.of(int[].class).getType());
12137dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(int[][].class, TypeToken.of(int[][].class).getType());
12147dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(String[].class, TypeToken.of(String[].class).getType());
12157dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Integer.class, new TypeToken<Integer>() {}.getType());
12167dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Integer.class, TypeToken.of(Integer.class).getType());
12177dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12187dd252788645e940eada959bdde927426e2531c9Paul Duffin
12197dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testMethod_getOwnerType() throws NoSuchMethodException {
12207dd252788645e940eada959bdde927426e2531c9Paul Duffin    Method sizeMethod = List.class.getMethod("size");
12217dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(List.class),
12227dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(List.class).method(sizeMethod).getOwnerType());
12237dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<List<String>>() {},
12247dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<List<String>>() {}.method(sizeMethod).getOwnerType());
12257dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12267dd252788645e940eada959bdde927426e2531c9Paul Duffin
12277dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testMethod_notDeclaredByType() throws NoSuchMethodException {
12287dd252788645e940eada959bdde927426e2531c9Paul Duffin    Method sizeMethod = Map.class.getMethod("size");
12297dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
12307dd252788645e940eada959bdde927426e2531c9Paul Duffin      TypeToken.of(List.class).method(sizeMethod);
12317dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
12327dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
12337dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12347dd252788645e940eada959bdde927426e2531c9Paul Duffin
12357dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testMethod_declaredBySuperclass() throws Exception {
12367dd252788645e940eada959bdde927426e2531c9Paul Duffin    Method toStringMethod = Object.class.getMethod("toString");
12377dd252788645e940eada959bdde927426e2531c9Paul Duffin    ImmutableList<String> list = ImmutableList.of("foo");
12387dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(list.toString(), TypeToken.of(List.class).method(toStringMethod).invoke(list));
12397dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12407dd252788645e940eada959bdde927426e2531c9Paul Duffin
12417dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends Number & List<String>> void testMethod_returnType_resolvedAgainstTypeBound()
12427dd252788645e940eada959bdde927426e2531c9Paul Duffin      throws NoSuchMethodException {
12437dd252788645e940eada959bdde927426e2531c9Paul Duffin    Method getMethod = List.class.getMethod("get", int.class);
12440888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Invokable<T, String> invokable = new TypeToken<T>(getClass()) {}
12457dd252788645e940eada959bdde927426e2531c9Paul Duffin        .method(getMethod)
12467dd252788645e940eada959bdde927426e2531c9Paul Duffin        .returning(String.class);
12470888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(TypeToken.of(String.class), invokable.getReturnType());
12487dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12497dd252788645e940eada959bdde927426e2531c9Paul Duffin
12507dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends List<String>> void testMethod_parameterTypes()
12517dd252788645e940eada959bdde927426e2531c9Paul Duffin      throws NoSuchMethodException {
12527dd252788645e940eada959bdde927426e2531c9Paul Duffin    Method setMethod = List.class.getMethod("set", int.class, Object.class);
12537dd252788645e940eada959bdde927426e2531c9Paul Duffin    Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.method(setMethod);
12547dd252788645e940eada959bdde927426e2531c9Paul Duffin    ImmutableList<Parameter> params = invokable.getParameters();
12557dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(2, params.size());
12567dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(int.class), params.get(0).getType());
12577dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(String.class), params.get(1).getType());
12587dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12597dd252788645e940eada959bdde927426e2531c9Paul Duffin
12600888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testMethod_equals() throws NoSuchMethodException {
12610888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Method getMethod = List.class.getMethod("get", int.class);
12620888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Method setMethod = List.class.getMethod("set", int.class, Object.class);
12630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    new EqualsTester()
12640888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(Invokable.from(getMethod), Invokable.from(getMethod))
12650888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(Invokable.from(setMethod))
12660888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(new TypeToken<List<Integer>>() {}.method(getMethod))
12670888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(new TypeToken<List<String>>() {}.method(getMethod))
12680888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(new TypeToken<List<Integer>>() {}.method(setMethod))
12690888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(new TypeToken<List<String>>() {}.method(setMethod))
12700888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .testEquals();
12710888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
12720888a09821a98ac0680fad765217302858e70fa4Paul Duffin
12737dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface Loser<E extends Throwable> {
12747dd252788645e940eada959bdde927426e2531c9Paul Duffin    void lose() throws E;
12757dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12767dd252788645e940eada959bdde927426e2531c9Paul Duffin
12777dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends Loser<AssertionError>> void testMethod_exceptionTypes()
12787dd252788645e940eada959bdde927426e2531c9Paul Duffin      throws NoSuchMethodException {
12797dd252788645e940eada959bdde927426e2531c9Paul Duffin    Method failMethod = Loser.class.getMethod("lose");
12807dd252788645e940eada959bdde927426e2531c9Paul Duffin    Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.method(failMethod);
12810888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class));
12827dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12837dd252788645e940eada959bdde927426e2531c9Paul Duffin
12847dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testConstructor_getOwnerType() throws NoSuchMethodException {
12857dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("rawtypes") // raw class ArrayList.class
12867dd252788645e940eada959bdde927426e2531c9Paul Duffin    Constructor<ArrayList> constructor = ArrayList.class.getConstructor();
12877dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(ArrayList.class),
12887dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(ArrayList.class).constructor(constructor).getOwnerType());
12897dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<ArrayList<String>>() {},
12907dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<ArrayList<String>>() {}.constructor(constructor).getOwnerType());
12917dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
12927dd252788645e940eada959bdde927426e2531c9Paul Duffin
12937dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testConstructor_notDeclaredByType() throws NoSuchMethodException {
12947dd252788645e940eada959bdde927426e2531c9Paul Duffin    Constructor<String> constructor = String.class.getConstructor();
12957dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
12967dd252788645e940eada959bdde927426e2531c9Paul Duffin      TypeToken.of(Object.class).constructor(constructor);
12977dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
12987dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
12997dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
13007dd252788645e940eada959bdde927426e2531c9Paul Duffin
13017dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testConstructor_declaredBySuperclass() throws NoSuchMethodException {
13027dd252788645e940eada959bdde927426e2531c9Paul Duffin    Constructor<Object> constructor = Object.class.getConstructor();
13037dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
13047dd252788645e940eada959bdde927426e2531c9Paul Duffin      TypeToken.of(String.class).constructor(constructor);
13057dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
13067dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
13077dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
13087dd252788645e940eada959bdde927426e2531c9Paul Duffin
13090888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testConstructor_equals() throws NoSuchMethodException {
13100888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Constructor<?> defaultConstructor = ArrayList.class.getConstructor();
13110888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Constructor<?> oneArgConstructor = ArrayList.class.getConstructor(int.class);
13120888a09821a98ac0680fad765217302858e70fa4Paul Duffin    new EqualsTester()
13130888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(Invokable.from(defaultConstructor), Invokable.from(defaultConstructor))
13140888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(Invokable.from(oneArgConstructor))
13150888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(new TypeToken<ArrayList<Integer>>() {}.constructor(defaultConstructor))
13160888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(new TypeToken<ArrayList<String>>() {}.constructor(defaultConstructor))
13170888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(new TypeToken<ArrayList<Integer>>() {}.constructor(oneArgConstructor))
13180888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(new TypeToken<ArrayList<String>>() {}.constructor(oneArgConstructor))
13190888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .testEquals();
13200888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
13210888a09821a98ac0680fad765217302858e70fa4Paul Duffin
13227dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class Container<T> {
13237dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unused")
13247dd252788645e940eada959bdde927426e2531c9Paul Duffin    public Container(T data) {}
13257dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
13267dd252788645e940eada959bdde927426e2531c9Paul Duffin
13277dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends Container<String>> void testConstructor_parameterTypes()
13287dd252788645e940eada959bdde927426e2531c9Paul Duffin      throws NoSuchMethodException {
13297dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("rawtypes") // Reflection API skew
13307dd252788645e940eada959bdde927426e2531c9Paul Duffin    Constructor<Container> constructor = Container.class.getConstructor(Object.class);
13317dd252788645e940eada959bdde927426e2531c9Paul Duffin    Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.constructor(constructor);
13327dd252788645e940eada959bdde927426e2531c9Paul Duffin    ImmutableList<Parameter> params = invokable.getParameters();
13337dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(1, params.size());
13347dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(TypeToken.of(String.class), params.get(0).getType());
13357dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
13367dd252788645e940eada959bdde927426e2531c9Paul Duffin
13377dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class CannotConstruct<E extends Throwable> {
13387dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unused")
13397dd252788645e940eada959bdde927426e2531c9Paul Duffin    public CannotConstruct() throws E {}
13407dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
13417dd252788645e940eada959bdde927426e2531c9Paul Duffin
13427dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T extends CannotConstruct<AssertionError>> void testConstructor_exceptionTypes()
13437dd252788645e940eada959bdde927426e2531c9Paul Duffin      throws NoSuchMethodException {
13447dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("rawtypes") // Reflection API skew
13457dd252788645e940eada959bdde927426e2531c9Paul Duffin    Constructor<CannotConstruct> constructor = CannotConstruct.class.getConstructor();
13467dd252788645e940eada959bdde927426e2531c9Paul Duffin    Invokable<T, ?> invokable = new TypeToken<T>(getClass()) {}.constructor(constructor);
13470888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class));
13480888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
13490888a09821a98ac0680fad765217302858e70fa4Paul Duffin
13500888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testRejectTypeVariable_class() {
13510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNoTypeVariable(String.class);
13520888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNoTypeVariable(String[].class);
13530888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNoTypeVariable(int[].class);
13540888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
13550888a09821a98ac0680fad765217302858e70fa4Paul Duffin
13560888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testRejectTypeVariable_parameterizedType() {
13570888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNoTypeVariable(new TypeCapture<Iterable<String>>() {}.capture());
13580888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
13590888a09821a98ac0680fad765217302858e70fa4Paul Duffin
13600888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testRejectTypeVariable_wildcardType() {
13610888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNoTypeVariable(
13620888a09821a98ac0680fad765217302858e70fa4Paul Duffin        new TypeCapture<Iterable<? extends String>>() {}.capture());
13630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNoTypeVariable(
13640888a09821a98ac0680fad765217302858e70fa4Paul Duffin        new TypeCapture<Iterable<? super String>>() {}.capture());
13650888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
13660888a09821a98ac0680fad765217302858e70fa4Paul Duffin
13670888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testRejectTypeVariable_genericArrayType() {
13680888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNoTypeVariable(
13690888a09821a98ac0680fad765217302858e70fa4Paul Duffin        new TypeCapture<Iterable<? extends String>[]>() {}.capture());
13700888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
13710888a09821a98ac0680fad765217302858e70fa4Paul Duffin
13720888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public <T> void testRejectTypeVariable_withTypeVariable() {
13730888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new TypeCapture<T>() {}.capture());
13740888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new TypeCapture<T[]>() {}.capture());
13750888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new TypeCapture<Iterable<T>>() {}.capture());
13760888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new TypeCapture<Map<String, T>>() {}.capture());
13770888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(
13780888a09821a98ac0680fad765217302858e70fa4Paul Duffin        new TypeCapture<Map<String, ? extends T>>() {}.capture());
13790888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(
13800888a09821a98ac0680fad765217302858e70fa4Paul Duffin        new TypeCapture<Map<String, ? super T[]>>() {}.capture());
13810888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
13820888a09821a98ac0680fad765217302858e70fa4Paul Duffin
13830888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static class From<K> {
13840888a09821a98ac0680fad765217302858e70fa4Paul Duffin    class To<V> {
13850888a09821a98ac0680fad765217302858e70fa4Paul Duffin      Type type() {
13860888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return new TypeToken<To<V>>(getClass()) {}.getType();
13870888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
13880888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
13890888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
13900888a09821a98ac0680fad765217302858e70fa4Paul Duffin
13910888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public <T> void testRejectTypeVariable_withOwnerType() {
13920888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // Neither has subclass
13930888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new From<Integer>().new To<String>().type());
13940888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new From<T>().new To<String>().type());
13950888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new From<Integer>().new To<T>().type());
13960888a09821a98ac0680fad765217302858e70fa4Paul Duffin
13970888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // Owner is subclassed
13980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new From<Integer>() {}.new To<String>().type());
13990888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new From<T>() {}.new To<String>().type());
14000888a09821a98ac0680fad765217302858e70fa4Paul Duffin
14010888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // Inner is subclassed
14020888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNoTypeVariable(new From<Integer>().new To<String>() {}.type());
14030888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new From<Integer>().new To<T>() {}.type());
14040888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new From<T>().new To<String>() {}.type());
14050888a09821a98ac0680fad765217302858e70fa4Paul Duffin
14060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // both subclassed
14070888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new From<T>() {}.new To<String>() {}.type());
14080888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNoTypeVariable(new From<Integer>() {}.new To<String>() {}.type());
14090888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertHasTypeVariable(new From<Integer>() {}.new To<T>() {}.type());
14100888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
14110888a09821a98ac0680fad765217302858e70fa4Paul Duffin
14120888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertHasTypeVariable(Type type) {
14130888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
14140888a09821a98ac0680fad765217302858e70fa4Paul Duffin      TypeToken.of(type).rejectTypeVariables();
14150888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("Should contain TypeVariable");
14160888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (IllegalArgumentException expected) {}
14170888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
14180888a09821a98ac0680fad765217302858e70fa4Paul Duffin
14190888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertNoTypeVariable(Type type) {
14200888a09821a98ac0680fad765217302858e70fa4Paul Duffin    TypeToken.of(type).rejectTypeVariables();
14217dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
14227dd252788645e940eada959bdde927426e2531c9Paul Duffin
14237dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class RawTypeConsistencyTester<T extends Enum<T> & CharSequence> {
14247dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract T returningT();
14257dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract void acceptT(T t);
14267dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract <X extends T> X returningX();
14277dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract <X> void acceptX(X x);
14287dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract <T2 extends Enum<T2> & CharSequence> T2 returningT2();
14297dd252788645e940eada959bdde927426e2531c9Paul Duffin    abstract <T2 extends CharSequence&Iterable<T2>> void acceptT2(T2 t2);
14307dd252788645e940eada959bdde927426e2531c9Paul Duffin
14317dd252788645e940eada959bdde927426e2531c9Paul Duffin    static void verifyConsitentRawType() {
14327dd252788645e940eada959bdde927426e2531c9Paul Duffin      for (Method method : RawTypeConsistencyTester.class.getDeclaredMethods()) {
14337dd252788645e940eada959bdde927426e2531c9Paul Duffin        assertEquals(method.getReturnType(), TypeToken.getRawType(method.getGenericReturnType()));
14347dd252788645e940eada959bdde927426e2531c9Paul Duffin        for (int i = 0; i < method.getParameterTypes().length; i++) {
14357dd252788645e940eada959bdde927426e2531c9Paul Duffin          assertEquals(method.getParameterTypes()[i],
14367dd252788645e940eada959bdde927426e2531c9Paul Duffin              TypeToken.getRawType(method.getGenericParameterTypes()[i]));
14377dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
14387dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
14397dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
14407dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
14417dd252788645e940eada959bdde927426e2531c9Paul Duffin
14427dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testRawTypes() throws Exception {
14437dd252788645e940eada959bdde927426e2531c9Paul Duffin    RawTypeConsistencyTester.verifyConsitentRawType();
14447dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Object.class, TypeToken.getRawType(Types.subtypeOf(Object.class)));
14457dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(CharSequence.class, TypeToken.getRawType(Types.subtypeOf(CharSequence.class)));
14467dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Object.class, TypeToken.getRawType(Types.supertypeOf(CharSequence.class)));
14477dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
14487dd252788645e940eada959bdde927426e2531c9Paul Duffin
14497dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class IKnowMyType<T> {
14507dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<T> type() {
14517dd252788645e940eada959bdde927426e2531c9Paul Duffin      return new TypeToken<T>(getClass()) {};
14527dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
14537dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
14547dd252788645e940eada959bdde927426e2531c9Paul Duffin
14557dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testTypeResolution() {
14567dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(String.class,
14577dd252788645e940eada959bdde927426e2531c9Paul Duffin        new IKnowMyType<String>() {}.type().getType());
14587dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeToken<Map<String, Integer>>() {},
14597dd252788645e940eada959bdde927426e2531c9Paul Duffin        new IKnowMyType<Map<String, Integer>>() {}.type());
14607dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
14617dd252788645e940eada959bdde927426e2531c9Paul Duffin
14627dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <A extends Iterable<? extends String>, B extends A> void testSerializable() {
14637dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(TypeToken.of(String.class));
14647dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(TypeToken.of(String.class).getTypes());
14657dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(TypeToken.of(String.class).getTypes().classes());
14667dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(TypeToken.of(String.class).getTypes().interfaces());
14677dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(TypeToken.of(String.class).getTypes().rawTypes());
14687dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(TypeToken.of(String.class).getTypes().classes().rawTypes());
14697dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(TypeToken.of(String.class).getTypes().interfaces().rawTypes());
14707dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(new TypeToken<int[]>() {});
14717dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(new TypeToken<Map<String, Integer>>() {});
14727dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(new IKnowMyType<Map<? super String, ? extends int[]>>() {}.type());
14737dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(TypeToken.of(new TypeCapture<B>() {}.capture()).getTypes().rawTypes());
14747dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
14757dd252788645e940eada959bdde927426e2531c9Paul Duffin      SerializableTester.reserialize(TypeToken.of(new TypeCapture<B>() {}.capture()));
14767dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
14777dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (RuntimeException expected) {}
14787dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
14797dd252788645e940eada959bdde927426e2531c9Paul Duffin
14807dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <A> void testSerializable_typeVariableNotSupported() {
14817dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
14827dd252788645e940eada959bdde927426e2531c9Paul Duffin      new ITryToSerializeMyTypeVariable<String>().go();
14837dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
14847dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (RuntimeException expected) {}
14857dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
14867dd252788645e940eada959bdde927426e2531c9Paul Duffin
14877dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class ITryToSerializeMyTypeVariable<T> {
14887dd252788645e940eada959bdde927426e2531c9Paul Duffin    void go() {
14897dd252788645e940eada959bdde927426e2531c9Paul Duffin      SerializableTester.reserialize(TypeToken.of(new TypeCapture<T>() {}.capture()));
14907dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
14917dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
14927dd252788645e940eada959bdde927426e2531c9Paul Duffin
14937dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static <T> T reserialize(T object) {
14947dd252788645e940eada959bdde927426e2531c9Paul Duffin    T copy = SerializableTester.reserialize(object);
14957dd252788645e940eada959bdde927426e2531c9Paul Duffin    new EqualsTester()
14967dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(object, copy)
14977dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testEquals();
14987dd252788645e940eada959bdde927426e2531c9Paul Duffin    return copy;
14997dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15007dd252788645e940eada959bdde927426e2531c9Paul Duffin
15017dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testTypeResolutionAfterReserialized() {
15027dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(new TypeToken<String>() {});
15037dd252788645e940eada959bdde927426e2531c9Paul Duffin    reserialize(new TypeToken<Map<String, Integer>>() {});
15047dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<Map<String, Integer>> reserialized = reserialize(
15057dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeToken<Map<String, Integer>>() {});
15067dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(reserialized, substitute(reserialized, String.class));
15077dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15087dd252788645e940eada959bdde927426e2531c9Paul Duffin
15097dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static <T, X> TypeToken<T> substitute(TypeToken<T> type, Class<X> arg) {
15107dd252788645e940eada959bdde927426e2531c9Paul Duffin    return type.where(new TypeParameter<X>() {}, arg);
15117dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15127dd252788645e940eada959bdde927426e2531c9Paul Duffin
15137dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class ToReproduceGenericSignatureFormatError<V> {
15147dd252788645e940eada959bdde927426e2531c9Paul Duffin    private abstract class BaseOuter {
15157dd252788645e940eada959bdde927426e2531c9Paul Duffin      abstract class BaseInner {}
15167dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
15177dd252788645e940eada959bdde927426e2531c9Paul Duffin    private abstract class SubOuter extends BaseOuter {
15187dd252788645e940eada959bdde927426e2531c9Paul Duffin      private abstract class SubInner extends BaseInner {}
15197dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
15207dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15217dd252788645e940eada959bdde927426e2531c9Paul Duffin
15227dd252788645e940eada959bdde927426e2531c9Paul Duffin  // For Guava bug http://code.google.com/p/guava-libraries/issues/detail?id=1025
15237dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testDespiteGenericSignatureFormatError() {
15247dd252788645e940eada959bdde927426e2531c9Paul Duffin    ImmutableSet.copyOf(
15257dd252788645e940eada959bdde927426e2531c9Paul Duffin        TypeToken.of(ToReproduceGenericSignatureFormatError.SubOuter.SubInner.class)
15267dd252788645e940eada959bdde927426e2531c9Paul Duffin            .getTypes()
15277dd252788645e940eada959bdde927426e2531c9Paul Duffin            .rawTypes());
15287dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15297dd252788645e940eada959bdde927426e2531c9Paul Duffin
15307dd252788645e940eada959bdde927426e2531c9Paul Duffin  private abstract static class Entry<K, V> {
15317dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<K> keyType() {
15327dd252788645e940eada959bdde927426e2531c9Paul Duffin      return new TypeToken<K>(getClass()) {};
15337dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
15347dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeToken<V> valueType() {
15357dd252788645e940eada959bdde927426e2531c9Paul Duffin      return new TypeToken<V>(getClass()) {};
15367dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
15377dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15387dd252788645e940eada959bdde927426e2531c9Paul Duffin
15397dd252788645e940eada959bdde927426e2531c9Paul Duffin  // The A and B type parameters are used inside the test to test type variable
15407dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <A, B> void testEquals() {
15417dd252788645e940eada959bdde927426e2531c9Paul Duffin    new EqualsTester()
15427dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(
15437dd252788645e940eada959bdde927426e2531c9Paul Duffin            TypeToken.of(String.class),
15447dd252788645e940eada959bdde927426e2531c9Paul Duffin            TypeToken.of(String.class),
15457dd252788645e940eada959bdde927426e2531c9Paul Duffin            new Entry<String, Integer>() {}.keyType(),
15467dd252788645e940eada959bdde927426e2531c9Paul Duffin            new Entry<Integer, String>() {}.valueType(),
15477dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<String>() {},
15487dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<String>() {})
15497dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(
15507dd252788645e940eada959bdde927426e2531c9Paul Duffin            TypeToken.of(Integer.class),
15517dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<Integer>() {},
15527dd252788645e940eada959bdde927426e2531c9Paul Duffin            new Entry<Integer, String>() {}.keyType(),
15537dd252788645e940eada959bdde927426e2531c9Paul Duffin            new Entry<String, Integer>() {}.valueType())
15547dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(
15557dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<List<String>>() {},
15567dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<List<String>>() {})
15577dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(
15587dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<List<?>>() {},
15597dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<List<?>>() {})
15607dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(
15617dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<Map<A, ?>>() {},
15627dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<Map<A, ?>>() {})
15637dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(
15647dd252788645e940eada959bdde927426e2531c9Paul Duffin            new TypeToken<Map<B, ?>>() {})
15657dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(
15667dd252788645e940eada959bdde927426e2531c9Paul Duffin            TypeToken.of(new TypeCapture<A>() {}.capture()),
15677dd252788645e940eada959bdde927426e2531c9Paul Duffin            TypeToken.of(new TypeCapture<A>() {}.capture()))
15687dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(TypeToken.of(new TypeCapture<B>() {}.capture()))
15697dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testEquals();
15707dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15717dd252788645e940eada959bdde927426e2531c9Paul Duffin
15727dd252788645e940eada959bdde927426e2531c9Paul Duffin  // T is used inside to test type variable
15737dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testToString() {
15747dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(String.class.getName(), new TypeToken<String>() {}.toString());
15757dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals("T", TypeToken.of(new TypeCapture<T>() {}.capture()).toString());
15767dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals("java.lang.String", new Entry<String, Integer>() {}.keyType().toString());
15777dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15787dd252788645e940eada959bdde927426e2531c9Paul Duffin
15797dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static <K, V> TypeToken<Map<K, V>> mapOf(Class<K> keyType, Class<V> valueType) {
15807dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new TypeToken<Map<K, V>>() {}
15817dd252788645e940eada959bdde927426e2531c9Paul Duffin        .where(new TypeParameter<K>() {}, keyType)
15827dd252788645e940eada959bdde927426e2531c9Paul Duffin        .where(new TypeParameter<V>() {}, valueType);
15837dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15847dd252788645e940eada959bdde927426e2531c9Paul Duffin
15857dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static <T> TypeToken<T[]> arrayOf(Class<T> componentType) {
15867dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new TypeToken<T[]>() {}
15877dd252788645e940eada959bdde927426e2531c9Paul Duffin        .where(new TypeParameter<T>() {}, componentType);
15887dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15897dd252788645e940eada959bdde927426e2531c9Paul Duffin
15907dd252788645e940eada959bdde927426e2531c9Paul Duffin  public <T> void testNulls() {
15917dd252788645e940eada959bdde927426e2531c9Paul Duffin    new NullPointerTester()
15927dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testAllPublicStaticMethods(TypeToken.class);
15937dd252788645e940eada959bdde927426e2531c9Paul Duffin    new NullPointerTester()
15947dd252788645e940eada959bdde927426e2531c9Paul Duffin        .setDefault(TypeParameter.class, new TypeParameter<T>() {})
15957dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testAllPublicInstanceMethods(TypeToken.of(String.class));
15967dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
15977dd252788645e940eada959bdde927426e2531c9Paul Duffin
15987dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class Assignability<From, To> {
15997dd252788645e940eada959bdde927426e2531c9Paul Duffin
16007dd252788645e940eada959bdde927426e2531c9Paul Duffin    boolean isAssignable() {
16017dd252788645e940eada959bdde927426e2531c9Paul Duffin      return new TypeToken<To>(getClass()) {}.isAssignableFrom(new TypeToken<From>(getClass()) {});
16027dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
16037dd252788645e940eada959bdde927426e2531c9Paul Duffin
16047dd252788645e940eada959bdde927426e2531c9Paul Duffin    static <From, To> Assignability<From, To> of() {
16057dd252788645e940eada959bdde927426e2531c9Paul Duffin      return new Assignability<From, To>();
16067dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
16077dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
16087dd252788645e940eada959bdde927426e2531c9Paul Duffin
16097dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void assertAssignable(TypeToken<?> from, TypeToken<?> to) {
16107dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertTrue(
16117dd252788645e940eada959bdde927426e2531c9Paul Duffin        from.getType() + " is expected to be assignable to " + to.getType(),
16127dd252788645e940eada959bdde927426e2531c9Paul Duffin        to.isAssignableFrom(from));
16137dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
16147dd252788645e940eada959bdde927426e2531c9Paul Duffin
16157dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void assertNotAssignable(TypeToken<?> from, TypeToken<?> to) {
16167dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertFalse(
16177dd252788645e940eada959bdde927426e2531c9Paul Duffin        from.getType() + " shouldn't be assignable to " + to.getType(),
16187dd252788645e940eada959bdde927426e2531c9Paul Duffin        to.isAssignableFrom(from));
16197dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
16207dd252788645e940eada959bdde927426e2531c9Paul Duffin
16217dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void assertHasArrayInterfaces(TypeToken<?> arrayType) {
16227dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(arrayInterfaces(), ImmutableSet.copyOf(arrayType.getGenericInterfaces()));
16237dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
16247dd252788645e940eada959bdde927426e2531c9Paul Duffin
16257dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static ImmutableSet<TypeToken<?>> arrayInterfaces() {
16267dd252788645e940eada959bdde927426e2531c9Paul Duffin    ImmutableSet.Builder<TypeToken<?>> builder = ImmutableSet.builder();
16277dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (Class<?> interfaceType : Object[].class.getInterfaces()) {
16287dd252788645e940eada959bdde927426e2531c9Paul Duffin      builder.add(TypeToken.of(interfaceType));
16297dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
16307dd252788645e940eada959bdde927426e2531c9Paul Duffin    return builder.build();
16317dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
16327dd252788645e940eada959bdde927426e2531c9Paul Duffin
16330888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertIsPrimitive(TypeToken<?> type) {
16340888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertTrue(type.isPrimitive());
16350888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNotWrapper(type);
16360888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(TypeToken.of(Primitives.wrap((Class<?>) type.getType())), type.wrap());
16370888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
16380888a09821a98ac0680fad765217302858e70fa4Paul Duffin
16390888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertNotPrimitive(TypeToken<?> type) {
16400888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFalse(type.isPrimitive());
16410888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertSame(type, type.wrap());
16420888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
16430888a09821a98ac0680fad765217302858e70fa4Paul Duffin
16440888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertIsWrapper(TypeToken<?> type) {
16450888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNotPrimitive(type);
16460888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(TypeToken.of(Primitives.unwrap((Class<?>) type.getType())), type.unwrap());
16470888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
16480888a09821a98ac0680fad765217302858e70fa4Paul Duffin
16490888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertNotWrapper(TypeToken<?> type) {
16500888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertSame(type, type.unwrap());
16510888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
16520888a09821a98ac0680fad765217302858e70fa4Paul Duffin
16530888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertNotPrimitiveNorWrapper(TypeToken<?> type) {
16540888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNotPrimitive(type);
16550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertNotWrapper(type);
16560888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
16570888a09821a98ac0680fad765217302858e70fa4Paul Duffin
16587dd252788645e940eada959bdde927426e2531c9Paul Duffin  private interface BaseInterface {}
16597dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class Base implements BaseInterface {}
16607dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class Sub extends Base {}
16617dd252788645e940eada959bdde927426e2531c9Paul Duffin
16620888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static CollectionSubject<?, Object, ?> assertThat(Collection<?> actual) {
16630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return ASSERT.that(Collections.<Object>unmodifiableCollection(actual));
16647dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
16657dd252788645e940eada959bdde927426e2531c9Paul Duffin}
1666