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