14f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit/**
24f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * Copyright (C) 2008 Google Inc.
34f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit *
44f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * Licensed under the Apache License, Version 2.0 (the "License");
54f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * you may not use this file except in compliance with the License.
64f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * You may obtain a copy of the License at
74f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit *
84f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * http://www.apache.org/licenses/LICENSE-2.0
94f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit *
104f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * Unless required by applicable law or agreed to in writing, software
114f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * distributed under the License is distributed on an "AS IS" BASIS,
124f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * See the License for the specific language governing permissions and
144f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * limitations under the License.
154f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit */
164f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
174f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitpackage com.google.inject;
184f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
194f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport static com.google.inject.Asserts.assertEqualsBothWays;
204f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport static com.google.inject.Asserts.assertNotSerializable;
214f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport static com.google.inject.util.Types.arrayOf;
224f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport static com.google.inject.util.Types.listOf;
234f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport static com.google.inject.util.Types.newParameterizedType;
244f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport static com.google.inject.util.Types.newParameterizedTypeWithOwner;
254f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport static com.google.inject.util.Types.setOf;
26b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
27b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.ImmutableList;
28b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.inject.util.Types;
29b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
30b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport junit.framework.TestCase;
31b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
324f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.io.IOException;
334f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.lang.reflect.Constructor;
344f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.lang.reflect.Field;
354f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.lang.reflect.Method;
364f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.lang.reflect.Type;
374f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.AbstractCollection;
384f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.AbstractList;
394f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.ArrayList;
404f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.Arrays;
414f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.Collection;
424f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.HashMap;
434f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.List;
444f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.Map;
454f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitimport java.util.Set;
464f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
474f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit/**
484f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * This test checks that TypeLiteral can perform type resolution on its members.
494f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit *
504f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit * @author jessewilson@google.com (Jesse Wilson)
514f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit */
524f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkitpublic class TypeLiteralTypeResolutionTest extends TestCase {
534f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type arrayListOfString = newParameterizedType(ArrayList.class, String.class);
544f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type hasGenericFieldsOfShort = newParameterizedTypeWithOwner(
554f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      getClass(), HasGenericFields.class, Short.class);
564f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type hasGenericConstructorOfShort = newParameterizedTypeWithOwner(
574f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      getClass(), GenericConstructor.class, Short.class);
584f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type throwerOfNpe = newParameterizedTypeWithOwner(
594f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      getClass(), Thrower.class, NullPointerException.class);
604f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type hasArrayOfShort = newParameterizedTypeWithOwner(getClass(), HasArray.class, Short.class);
614f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type hasRelatedOfString = newParameterizedTypeWithOwner(
624f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      getClass(), HasRelated.class, String.class, String.class);
634f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type mapK = Map.class.getTypeParameters()[0];
644f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type hashMapK = HashMap.class.getTypeParameters()[0];
654f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type setEntryKV;
664f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Type entryStringInteger = setOf(newParameterizedTypeWithOwner(
674f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      Map.class, Map.Entry.class, String.class, Integer.class));
684f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Field list;
694f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Field instance;
704f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Constructor<GenericConstructor> newHasGenericConstructor;
714f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Constructor<Thrower> newThrower;
724f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Constructor newString;
734f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Method stringIndexOf;
744f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Method comparableCompareTo;
754f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Method getArray;
764f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Method getSetOfArray;
774f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Method echo;
784f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  Method throwS;
794f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
804f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  @Override protected void setUp() throws Exception {
814f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    super.setUp();
824f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
834f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    list = HasGenericFields.class.getField("list");
844f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    instance = HasGenericFields.class.getField("instance");
854f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    newHasGenericConstructor = GenericConstructor.class.getConstructor(Object.class, Object.class);
864f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    newThrower = Thrower.class.getConstructor();
874f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    stringIndexOf = String.class.getMethod("indexOf", String.class);
884f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    newString = String.class.getConstructor(String.class);
894f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    comparableCompareTo = Comparable.class.getMethod("compareTo", Object.class);
904f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    getArray = HasArray.class.getMethod("getArray");
914f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    getSetOfArray = HasArray.class.getMethod("getSetOfArray");
924f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    echo = HasRelated.class.getMethod("echo", Object.class);
934f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    throwS = Thrower.class.getMethod("throwS");
944f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    setEntryKV = HashMap.class.getMethod("entrySet").getGenericReturnType();
954f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
964f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
974f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testDirectInheritance() throws NoSuchMethodException {
984f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
994f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEquals(listOf(String.class),
1004272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        resolver.getReturnType(List.class.getMethod("subList", int.class, int.class)).getType());
1014272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(ImmutableList.<TypeLiteral<?>>of(TypeLiteral.get(String.class)),
1024f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        resolver.getParameterTypes(Collection.class.getMethod("add", Object.class)));
1034f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
104ec76179f50f9d8c340b311c6b019c00526566b66sberlin
1054f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testGenericSupertype() {
1064f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
1074f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEquals(newParameterizedType(Collection.class, String.class),
1084272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        resolver.getSupertype(Collection.class).getType());
1094f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEquals(newParameterizedType(Iterable.class, String.class),
1104272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        resolver.getSupertype(Iterable.class).getType());
1114f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEquals(newParameterizedType(AbstractList.class, String.class),
1124272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        resolver.getSupertype(AbstractList.class).getType());
1134272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(Object.class, resolver.getSupertype(Object.class).getType());
1144f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1154f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1164f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testRecursiveTypeVariable() {
1174f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> resolver = TypeLiteral.get(MyInteger.class);
1184272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(MyInteger.class, resolver.getParameterTypes(comparableCompareTo).get(0).getType());
1194f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1204f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1214f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  interface MyComparable<E extends MyComparable<E>> extends Comparable<E> {}
1224f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1234f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  static class MyInteger implements MyComparable<MyInteger> {
1244f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    int value;
1254f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    public int compareTo(MyInteger o) {
1264f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      return value - o.value;
1274f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
1284f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
129ec76179f50f9d8c340b311c6b019c00526566b66sberlin
1304f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testFields() {
1314f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> resolver = TypeLiteral.get(hasGenericFieldsOfShort);
1324272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(listOf(Short.class), resolver.getFieldType(list).getType());
1334272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(Short.class, resolver.getFieldType(instance).getType());
1344f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1354f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1364f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  static class HasGenericFields<T> {
1374f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    public List<T> list;
1384f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    public T instance;
1394f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1404f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1414f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testGenericConstructor() throws NoSuchMethodException {
1424f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> resolver = TypeLiteral.get(hasGenericConstructorOfShort);
1434272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(Short.class,
1444272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        resolver.getParameterTypes(newHasGenericConstructor).get(0).getType());
1454f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1464f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1474f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  static class GenericConstructor<S> {
1484f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    @SuppressWarnings("UnusedDeclaration")
1494f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    public <T> GenericConstructor(S s, T t) {}
1504f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1514f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1524f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testThrowsExceptions() {
1534272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    TypeLiteral<?> type = TypeLiteral.get(throwerOfNpe);
1544272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(NullPointerException.class, type.getExceptionTypes(newThrower).get(0).getType());
1554272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(NullPointerException.class, type.getExceptionTypes(throwS).get(0).getType());
1564f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1574f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1584f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  static class Thrower<S extends Exception> {
1594f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    public Thrower() throws S {}
1604f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    public void throwS() throws S {}
1614f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1624f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1634f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testArrays() {
1644f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> resolver = TypeLiteral.get(hasArrayOfShort);
1654272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(arrayOf(Short.class), resolver.getReturnType(getArray).getType());
1664272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(setOf(arrayOf(Short.class)), resolver.getReturnType(getSetOfArray).getType());
1674f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1684f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1694f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  static interface HasArray<T extends Number> {
1704f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    T[] getArray();
1714f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    Set<T[]> getSetOfArray();
1724f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1734f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1744f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testRelatedTypeVariables() {
1754f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> resolver = TypeLiteral.get(hasRelatedOfString);
1764272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(String.class, resolver.getParameterTypes(echo).get(0).getType());
1774272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(String.class, resolver.getReturnType(echo).getType());
1784f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1794f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1804f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  interface HasRelated<T, R extends T> {
1814f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    T echo(R r);
1824f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1834f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1844f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  /** Ensure the cache doesn't cache too much */
1854f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testCachingAndReindexing() throws NoSuchMethodException {
1864f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> resolver = TypeLiteral.get(
1874f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        newParameterizedTypeWithOwner(getClass(), HasLists.class, String.class, Short.class));
1884f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEquals(listOf(String.class),
1894272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        resolver.getReturnType(HasLists.class.getMethod("listS")).getType());
1904f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEquals(listOf(Short.class),
1914272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        resolver.getReturnType(HasLists.class.getMethod("listT")).getType());
1924f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1934f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
1944f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  interface HasLists<S, T> {
1954f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    List<S> listS();
1964f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    List<T> listT();
1974f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    List<Map.Entry<S, T>> listEntries();
1984f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
1994f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2004f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testUnsupportedQueries() throws NoSuchMethodException {
2014f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
2024f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2034f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    try {
2044f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      resolver.getExceptionTypes(stringIndexOf);
2054f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      fail();
2064f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    } catch (IllegalArgumentException e) {
2074f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a "
2084f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          + "supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
2094f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
2104f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    try {
2114f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      resolver.getParameterTypes(stringIndexOf);
2124f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      fail();
2134f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    } catch (Exception e) {
2144f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a "
2154f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          + "supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
2164f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
2174f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    try {
2184f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      resolver.getReturnType(stringIndexOf);
2194f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      fail();
2204f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    } catch (Exception e) {
2214f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a "
2224f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          + "supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
2234f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
2244f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    try {
2254f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      resolver.getSupertype(String.class);
2264f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      fail();
2274f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    } catch (Exception e) {
2284f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      assertEquals("class java.lang.String is not a supertype of "
2294f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          + "java.util.ArrayList<java.lang.String>", e.getMessage());
2304f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
2314f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    try {
2324f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      resolver.getExceptionTypes(newString);
2334f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      fail();
2344f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    } catch (Exception e) {
2354f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      assertEquals("public java.lang.String(java.lang.String) does not construct "
2364f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          + "a supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
2374f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
2384f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    try {
2394f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      resolver.getParameterTypes(newString);
2404f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      fail();
2414f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    } catch (Exception e) {
2424f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit      assertEquals("public java.lang.String(java.lang.String) does not construct "
2434f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit          + "a supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
2444f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    }
2454f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
2464f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2474f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testResolve() {
2484f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> typeResolver = TypeLiteral.get(StringIntegerMap.class);
2494272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(String.class, typeResolver.resolveType(mapK));
2504f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2514f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    typeResolver = new TypeLiteral<Map<String, Integer>>() {};
2524272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(String.class, typeResolver.resolveType(mapK));
2534272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(Types.mapOf(String.class, Integer.class),
2544272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        typeResolver.getSupertype(Map.class).getType());
2554f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2564f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    typeResolver = new TypeLiteral<BetterMap<String, Integer>>() {};
2574272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(String.class, typeResolver.resolveType(mapK));
2584f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2594f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    typeResolver = new TypeLiteral<BestMap<String, Integer>>() {};
2604272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(String.class, typeResolver.resolveType(mapK));
2614f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2624f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    typeResolver = TypeLiteral.get(StringIntegerHashMap.class);
2634272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(String.class, typeResolver.resolveType(mapK));
2644272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(String.class, typeResolver.resolveType(hashMapK));
2654272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(entryStringInteger, typeResolver.resolveType(setEntryKV));
2664272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType());
2674f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
2684f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2694f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testOnObject() {
2704f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> typeResolver = TypeLiteral.get(Object.class);
2714272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType());
2724f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEquals(Object.class, typeResolver.getRawType());
2734f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2744f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    // interfaces also resolve Object
2754f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    typeResolver = TypeLiteral.get(Types.setOf(Integer.class));
2764272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType());
2774f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
2784f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2794f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  interface StringIntegerMap extends Map<String, Integer> {}
2804f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  interface BetterMap<K1, V1> extends Map<K1, V1> {}
2814f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  interface BestMap<K2, V2> extends BetterMap<K2, V2> {}
2824f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  static class StringIntegerHashMap extends HashMap<String, Integer> {}
2834f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2844f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testGetSupertype() {
2854f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<AbstractList<String>> listOfString = new TypeLiteral<AbstractList<String>>() {};
2864f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEquals(Types.newParameterizedType(AbstractCollection.class, String.class),
2874272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        listOfString.getSupertype(AbstractCollection.class).getType());
2884f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2894f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral arrayListOfE = TypeLiteral.get(newParameterizedType(
2904f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit        ArrayList.class, ArrayList.class.getTypeParameters()));
2914272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit    assertEquals(
2924272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        newParameterizedType(AbstractCollection.class, ArrayList.class.getTypeParameters()),
2934272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        arrayListOfE.getSupertype(AbstractCollection.class).getType());
2944f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
2954f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
2964f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testGetSupertypeForArraysAsList() {
2974f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    Class<? extends List> arraysAsListClass = Arrays.asList().getClass();
2984f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    Type anotherE = arraysAsListClass.getTypeParameters()[0];
2994f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral type = TypeLiteral.get(newParameterizedType(AbstractList.class, anotherE));
3004f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEquals(newParameterizedType(AbstractCollection.class, anotherE),
3014272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        type.getSupertype(AbstractCollection.class).getType());
3024f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
3034f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3048d13d41fadf5b304288f4dedf2435fb518209366limpbizkit  public void testWildcards() throws NoSuchFieldException {
3058d13d41fadf5b304288f4dedf2435fb518209366limpbizkit    TypeLiteral<Parameterized<String>> ofString = new TypeLiteral<Parameterized<String>>() {};
3068d13d41fadf5b304288f4dedf2435fb518209366limpbizkit
3078d13d41fadf5b304288f4dedf2435fb518209366limpbizkit    assertEquals(new TypeLiteral<List<String>>() {}.getType(),
3084272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        ofString.getFieldType(Parameterized.class.getField("t")).getType());
3098d13d41fadf5b304288f4dedf2435fb518209366limpbizkit    assertEquals(new TypeLiteral<List<? extends String>>() {}.getType(),
3104272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        ofString.getFieldType(Parameterized.class.getField("extendsT")).getType());
3118d13d41fadf5b304288f4dedf2435fb518209366limpbizkit    assertEquals(new TypeLiteral<List<? super String>>() {}.getType(),
3124272aef70de48e239e9f70ab10b0becefd3030cblimpbizkit        ofString.getFieldType(Parameterized.class.getField("superT")).getType());
3138d13d41fadf5b304288f4dedf2435fb518209366limpbizkit  }
3148d13d41fadf5b304288f4dedf2435fb518209366limpbizkit
3158d13d41fadf5b304288f4dedf2435fb518209366limpbizkit  static class Parameterized<T> {
3168d13d41fadf5b304288f4dedf2435fb518209366limpbizkit    public List<T> t;
3178d13d41fadf5b304288f4dedf2435fb518209366limpbizkit    public List<? extends T> extendsT;
3188d13d41fadf5b304288f4dedf2435fb518209366limpbizkit    public List<? super T> superT;
3198d13d41fadf5b304288f4dedf2435fb518209366limpbizkit  }
3208d13d41fadf5b304288f4dedf2435fb518209366limpbizkit
321ec76179f50f9d8c340b311c6b019c00526566b66sberlin  // TODO(jessewilson): tests for tricky bounded types like <T extends Collection, Serializable>
3224f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit
3234f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  public void testEqualsAndHashCode() throws IOException {
3244f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> a1 = TypeLiteral.get(arrayListOfString);
3254f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> a2 = TypeLiteral.get(arrayListOfString);
3264f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    TypeLiteral<?> b = TypeLiteral.get(listOf(String.class));
3274f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertEqualsBothWays(a1, a2);
3284f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertNotSerializable(a1);
3294f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit    assertFalse(a1.equals(b));
3304f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit  }
3314f5d1f7f1b88b7ee0aef7e70fc70ce824b6ceb22limpbizkit}
332