17dd252788645e940eada959bdde927426e2531c9Paul Duffin/*
27dd252788645e940eada959bdde927426e2531c9Paul Duffin * Copyright (C) 2011 The Guava Authors
37dd252788645e940eada959bdde927426e2531c9Paul Duffin *
47dd252788645e940eada959bdde927426e2531c9Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
57dd252788645e940eada959bdde927426e2531c9Paul Duffin * you may not use this file except in compliance with the License.
67dd252788645e940eada959bdde927426e2531c9Paul Duffin * You may obtain a copy of the License at
77dd252788645e940eada959bdde927426e2531c9Paul Duffin *
87dd252788645e940eada959bdde927426e2531c9Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
97dd252788645e940eada959bdde927426e2531c9Paul Duffin *
107dd252788645e940eada959bdde927426e2531c9Paul Duffin * Unless required by applicable law or agreed to in writing, software
117dd252788645e940eada959bdde927426e2531c9Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
127dd252788645e940eada959bdde927426e2531c9Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137dd252788645e940eada959bdde927426e2531c9Paul Duffin * See the License for the specific language governing permissions and
147dd252788645e940eada959bdde927426e2531c9Paul Duffin * limitations under the License.
157dd252788645e940eada959bdde927426e2531c9Paul Duffin */
167dd252788645e940eada959bdde927426e2531c9Paul Duffin
177dd252788645e940eada959bdde927426e2531c9Paul Duffinpackage com.google.common.reflect;
187dd252788645e940eada959bdde927426e2531c9Paul Duffin
197dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static java.util.Arrays.asList;
200888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static org.truth0.Truth.ASSERT;
217dd252788645e940eada959bdde927426e2531c9Paul Duffin
220888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.collect.Lists;
237dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.testing.EqualsTester;
247dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.testing.NullPointerTester;
257dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.testing.NullPointerTester.Visibility;
267dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.testing.SerializableTester;
277dd252788645e940eada959bdde927426e2531c9Paul Duffin
280888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport junit.framework.TestCase;
290888a09821a98ac0680fad765217302858e70fa4Paul Duffin
307dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.GenericArrayType;
317dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.GenericDeclaration;
327dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.ParameterizedType;
337dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Type;
347dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.TypeVariable;
357dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.WildcardType;
367dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Arrays;
377dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.HashMap;
387dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.List;
397dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Map;
407dd252788645e940eada959bdde927426e2531c9Paul Duffin
417dd252788645e940eada959bdde927426e2531c9Paul Duffin/**
427dd252788645e940eada959bdde927426e2531c9Paul Duffin * Tests for {@link Types}.
437dd252788645e940eada959bdde927426e2531c9Paul Duffin *
447dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Ben Yu
457dd252788645e940eada959bdde927426e2531c9Paul Duffin */
467dd252788645e940eada959bdde927426e2531c9Paul Duffinpublic class TypesTest extends TestCase {
477dd252788645e940eada959bdde927426e2531c9Paul Duffin
487dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedType_ownerTypeImplied() throws Exception {
497dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType jvmType = (ParameterizedType)
507dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeCapture<Map.Entry<String, Integer>>() {}.capture();
517dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType ourType = Types.newParameterizedType(
527dd252788645e940eada959bdde927426e2531c9Paul Duffin        Map.Entry.class, String.class, Integer.class);
537dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType, ourType);
547dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Map.class, ourType.getOwnerType());
557dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
567dd252788645e940eada959bdde927426e2531c9Paul Duffin
577dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedType() {
587dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType jvmType = (ParameterizedType)
597dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeCapture<HashMap<String, int[][]>>() {}.capture();
607dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType ourType = Types.newParameterizedType(
617dd252788645e940eada959bdde927426e2531c9Paul Duffin        HashMap.class, String.class, int[][].class);
627dd252788645e940eada959bdde927426e2531c9Paul Duffin
637dd252788645e940eada959bdde927426e2531c9Paul Duffin    new EqualsTester()
647dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(jvmType, ourType)
657dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testEquals();
667dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType.toString(), ourType.toString());
677dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType.hashCode(), ourType.hashCode());
687dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(HashMap.class, ourType.getRawType());
690888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(ourType.getActualTypeArguments())
707dd252788645e940eada959bdde927426e2531c9Paul Duffin        .iteratesOverSequence(jvmType.getActualTypeArguments());
717dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Arrays.asList(
727dd252788645e940eada959bdde927426e2531c9Paul Duffin            String.class,
737dd252788645e940eada959bdde927426e2531c9Paul Duffin            Types.newArrayType(Types.newArrayType(int.class))),
747dd252788645e940eada959bdde927426e2531c9Paul Duffin        Arrays.asList(ourType.getActualTypeArguments()));
757dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(null, ourType.getOwnerType());
767dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
777dd252788645e940eada959bdde927426e2531c9Paul Duffin
787dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedType_nonStaticLocalClass() {
797dd252788645e940eada959bdde927426e2531c9Paul Duffin    class LocalClass<T> {}
807dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type jvmType = new LocalClass<String>() {}.getClass().getGenericSuperclass();
817dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type ourType = Types.newParameterizedType(LocalClass.class, String.class);
827dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType, ourType);
837dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
847dd252788645e940eada959bdde927426e2531c9Paul Duffin
857dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedType_staticLocalClass() {
867dd252788645e940eada959bdde927426e2531c9Paul Duffin    doTestNewParameterizedType_staticLocalClass();
877dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
887dd252788645e940eada959bdde927426e2531c9Paul Duffin
897dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void doTestNewParameterizedType_staticLocalClass() {
907dd252788645e940eada959bdde927426e2531c9Paul Duffin    class LocalClass<T> {}
917dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type jvmType = new LocalClass<String>() {}.getClass().getGenericSuperclass();
927dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type ourType = Types.newParameterizedType(LocalClass.class, String.class);
937dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType, ourType);
947dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
957dd252788645e940eada959bdde927426e2531c9Paul Duffin
967dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedTypeWithOwner() {
977dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType jvmType = (ParameterizedType)
987dd252788645e940eada959bdde927426e2531c9Paul Duffin        new TypeCapture<Map.Entry<String, int[][]>>() {}.capture();
997dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType ourType = Types.newParameterizedTypeWithOwner(
1007dd252788645e940eada959bdde927426e2531c9Paul Duffin        Map.class, Map.Entry.class, String.class, int[][].class);
1017dd252788645e940eada959bdde927426e2531c9Paul Duffin
1027dd252788645e940eada959bdde927426e2531c9Paul Duffin    new EqualsTester()
1037dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(jvmType, ourType)
1047dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(new TypeCapture<Map.Entry<String, String>>() {}.capture())
1057dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(new TypeCapture<Map<String, Integer>>() {}.capture())
1067dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testEquals();
1077dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType.toString(), ourType.toString());
1087dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Map.class, ourType.getOwnerType());
1097dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Map.Entry.class, ourType.getRawType());
1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(ourType.getActualTypeArguments())
1117dd252788645e940eada959bdde927426e2531c9Paul Duffin        .iteratesOverSequence(jvmType.getActualTypeArguments());
1127dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1137dd252788645e940eada959bdde927426e2531c9Paul Duffin
1147dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedType_serializable() {
1157dd252788645e940eada959bdde927426e2531c9Paul Duffin    SerializableTester.reserializeAndAssert(Types.newParameterizedType(
1167dd252788645e940eada959bdde927426e2531c9Paul Duffin        Map.Entry.class, String.class, Integer.class));
1177dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1187dd252788645e940eada959bdde927426e2531c9Paul Duffin
1197dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedType_ownerMismatch() {
1207dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
1217dd252788645e940eada959bdde927426e2531c9Paul Duffin      Types.newParameterizedTypeWithOwner(
1227dd252788645e940eada959bdde927426e2531c9Paul Duffin          Number.class, List.class, String.class);
1237dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
1247dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
1257dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1267dd252788645e940eada959bdde927426e2531c9Paul Duffin
1277dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedType_ownerMissing() {
1287dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(
1297dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.newParameterizedType(Map.Entry.class, String.class, Integer.class),
1307dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.newParameterizedTypeWithOwner(
1317dd252788645e940eada959bdde927426e2531c9Paul Duffin            null, Map.Entry.class, String.class, Integer.class));
1327dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1337dd252788645e940eada959bdde927426e2531c9Paul Duffin
1347dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedType_invalidTypeParameters() {
1357dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
1367dd252788645e940eada959bdde927426e2531c9Paul Duffin      Types.newParameterizedTypeWithOwner(
1377dd252788645e940eada959bdde927426e2531c9Paul Duffin          Map.class, Map.Entry.class, String.class);
1387dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
1397dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
1407dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1417dd252788645e940eada959bdde927426e2531c9Paul Duffin
1427dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedType_primitiveTypeParameters() {
1437dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
1447dd252788645e940eada959bdde927426e2531c9Paul Duffin      Types.newParameterizedTypeWithOwner(
1457dd252788645e940eada959bdde927426e2531c9Paul Duffin          Map.class, Map.Entry.class, int.class, int.class);
1467dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
1477dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
1487dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1497dd252788645e940eada959bdde927426e2531c9Paul Duffin
1507dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewArrayType() {
1517dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type jvmType1 = new TypeCapture<List<String>[]>() {}.capture();
1527dd252788645e940eada959bdde927426e2531c9Paul Duffin    GenericArrayType ourType1 = (GenericArrayType) Types.newArrayType(
1537dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.newParameterizedType(List.class, String.class));
1547dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type jvmType2 = new TypeCapture<List[]>() {}.capture();
1557dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type ourType2 = Types.newArrayType(List.class);
1567dd252788645e940eada959bdde927426e2531c9Paul Duffin    new EqualsTester()
1577dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(jvmType1, ourType1)
1587dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(jvmType2, ourType2)
1597dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testEquals();
1607dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(new TypeCapture<List<String>>() {}.capture(),
1617dd252788645e940eada959bdde927426e2531c9Paul Duffin        ourType1.getGenericComponentType());
1627dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType1.toString(), ourType1.toString());
1637dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType2.toString(), ourType2.toString());
1647dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1657dd252788645e940eada959bdde927426e2531c9Paul Duffin
1667dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewArrayTypeOfArray() {
1677dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type jvmType = new TypeCapture<int[][]>() {}.capture();
1687dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type ourType = Types.newArrayType(int[].class);
1697dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType.toString(), ourType.toString());
1707dd252788645e940eada959bdde927426e2531c9Paul Duffin    new EqualsTester()
1717dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(jvmType, ourType)
1727dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testEquals();
1737dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1747dd252788645e940eada959bdde927426e2531c9Paul Duffin
1757dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewArrayType_primitive() {
1767dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type jvmType = new TypeCapture<int[]>() {}.capture();
1777dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type ourType = Types.newArrayType(int.class);
1787dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(jvmType.toString(), ourType.toString());
1797dd252788645e940eada959bdde927426e2531c9Paul Duffin    new EqualsTester()
1807dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(jvmType, ourType)
1817dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testEquals();
1827dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1837dd252788645e940eada959bdde927426e2531c9Paul Duffin
1847dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewArrayType_upperBoundedWildcard() {
1857dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type wildcard = Types.subtypeOf(Number.class);
1867dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Types.subtypeOf(Number[].class), Types.newArrayType(wildcard));
1877dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1887dd252788645e940eada959bdde927426e2531c9Paul Duffin
1897dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewArrayType_lowerBoundedWildcard() {
1907dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type wildcard = Types.supertypeOf(Number.class);
1917dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Types.supertypeOf(Number[].class), Types.newArrayType(wildcard));
1927dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1937dd252788645e940eada959bdde927426e2531c9Paul Duffin
1947dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewArrayType_serializable() {
1957dd252788645e940eada959bdde927426e2531c9Paul Duffin    SerializableTester.reserializeAndAssert(
1967dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.newArrayType(int[].class));
1977dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1987dd252788645e940eada959bdde927426e2531c9Paul Duffin
1997dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class WithWildcardType {
2007dd252788645e940eada959bdde927426e2531c9Paul Duffin
2017dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unused")
2027dd252788645e940eada959bdde927426e2531c9Paul Duffin    void withoutBound(List<?> list) {}
2037dd252788645e940eada959bdde927426e2531c9Paul Duffin
2047dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unused")
2057dd252788645e940eada959bdde927426e2531c9Paul Duffin    void withObjectBound(List<? extends Object> list) {}
2067dd252788645e940eada959bdde927426e2531c9Paul Duffin
2077dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unused")
2087dd252788645e940eada959bdde927426e2531c9Paul Duffin    void withUpperBound(List<? extends int[][]> list) {}
2097dd252788645e940eada959bdde927426e2531c9Paul Duffin
2107dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unused")
2117dd252788645e940eada959bdde927426e2531c9Paul Duffin    void withLowerBound(List<? super String[][]> list) {}
2127dd252788645e940eada959bdde927426e2531c9Paul Duffin
2137dd252788645e940eada959bdde927426e2531c9Paul Duffin    static WildcardType getWildcardType(String methodName) throws Exception {
2147dd252788645e940eada959bdde927426e2531c9Paul Duffin      ParameterizedType parameterType = (ParameterizedType)
2157dd252788645e940eada959bdde927426e2531c9Paul Duffin          WithWildcardType.class
2167dd252788645e940eada959bdde927426e2531c9Paul Duffin              .getDeclaredMethod(methodName, List.class)
2177dd252788645e940eada959bdde927426e2531c9Paul Duffin              .getGenericParameterTypes()[0];
2187dd252788645e940eada959bdde927426e2531c9Paul Duffin      return (WildcardType) parameterType.getActualTypeArguments()[0];
2197dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2207dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2217dd252788645e940eada959bdde927426e2531c9Paul Duffin
2227dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewWildcardType() throws Exception {
2237dd252788645e940eada959bdde927426e2531c9Paul Duffin    WildcardType noBoundJvmType =
2247dd252788645e940eada959bdde927426e2531c9Paul Duffin        WithWildcardType.getWildcardType("withoutBound");
2257dd252788645e940eada959bdde927426e2531c9Paul Duffin    WildcardType objectBoundJvmType =
2267dd252788645e940eada959bdde927426e2531c9Paul Duffin        WithWildcardType.getWildcardType("withObjectBound");
2277dd252788645e940eada959bdde927426e2531c9Paul Duffin    WildcardType upperBoundJvmType =
2287dd252788645e940eada959bdde927426e2531c9Paul Duffin        WithWildcardType.getWildcardType("withUpperBound");
2297dd252788645e940eada959bdde927426e2531c9Paul Duffin    WildcardType lowerBoundJvmType =
2307dd252788645e940eada959bdde927426e2531c9Paul Duffin        WithWildcardType.getWildcardType("withLowerBound");
2317dd252788645e940eada959bdde927426e2531c9Paul Duffin    WildcardType objectBound =
2327dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.subtypeOf(Object.class);
2337dd252788645e940eada959bdde927426e2531c9Paul Duffin    WildcardType upperBound =
2347dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.subtypeOf(int[][].class);
2357dd252788645e940eada959bdde927426e2531c9Paul Duffin    WildcardType lowerBound =
2367dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.supertypeOf(String[][].class);
2377dd252788645e940eada959bdde927426e2531c9Paul Duffin
2387dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEqualWildcardType(noBoundJvmType, objectBound);
2397dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEqualWildcardType(objectBoundJvmType, objectBound);
2407dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEqualWildcardType(upperBoundJvmType, upperBound);
2417dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEqualWildcardType(lowerBoundJvmType, lowerBound);
2427dd252788645e940eada959bdde927426e2531c9Paul Duffin
2437dd252788645e940eada959bdde927426e2531c9Paul Duffin    new EqualsTester()
2447dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(
2457dd252788645e940eada959bdde927426e2531c9Paul Duffin            noBoundJvmType, objectBoundJvmType, objectBound)
2467dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(upperBoundJvmType, upperBound)
2477dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(lowerBoundJvmType, lowerBound)
2487dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testEquals();
2497dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2507dd252788645e940eada959bdde927426e2531c9Paul Duffin
2517dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewWildcardType_primitiveTypeBound() {
2527dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
2537dd252788645e940eada959bdde927426e2531c9Paul Duffin      Types.subtypeOf(int.class);
2547dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
2557dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
2567dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2577dd252788645e940eada959bdde927426e2531c9Paul Duffin
2587dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewWildcardType_serializable() {
2597dd252788645e940eada959bdde927426e2531c9Paul Duffin    SerializableTester.reserializeAndAssert(
2607dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.supertypeOf(String.class));
2617dd252788645e940eada959bdde927426e2531c9Paul Duffin    SerializableTester.reserializeAndAssert(
2627dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.subtypeOf(String.class));
2637dd252788645e940eada959bdde927426e2531c9Paul Duffin    SerializableTester.reserializeAndAssert(
2647dd252788645e940eada959bdde927426e2531c9Paul Duffin        Types.subtypeOf(Object.class));
2657dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2667dd252788645e940eada959bdde927426e2531c9Paul Duffin
2677dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void assertEqualWildcardType(
2687dd252788645e940eada959bdde927426e2531c9Paul Duffin      WildcardType expected, WildcardType actual) {
2697dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(expected.toString(), actual.toString());
2707dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(actual.toString(), expected.hashCode(), actual.hashCode());
2710888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(actual.getLowerBounds())
2720888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactlyAs(asList(expected.getLowerBounds())).inOrder();
2730888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(actual.getUpperBounds())
2740888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .has().exactlyAs(asList(expected.getUpperBounds())).inOrder();
2757dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2767dd252788645e940eada959bdde927426e2531c9Paul Duffin
2777dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static class WithTypeVariable {
2787dd252788645e940eada959bdde927426e2531c9Paul Duffin
2797dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unused")
2807dd252788645e940eada959bdde927426e2531c9Paul Duffin    <T> void withoutBound(List<T> list) {}
2817dd252788645e940eada959bdde927426e2531c9Paul Duffin
2827dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unused")
2837dd252788645e940eada959bdde927426e2531c9Paul Duffin    <T extends Object> void withObjectBound(List<T> list) {}
2847dd252788645e940eada959bdde927426e2531c9Paul Duffin
2857dd252788645e940eada959bdde927426e2531c9Paul Duffin    @SuppressWarnings("unused")
2867dd252788645e940eada959bdde927426e2531c9Paul Duffin    <T extends Number & CharSequence> void withUpperBound(List<T> list) {}
2877dd252788645e940eada959bdde927426e2531c9Paul Duffin
2887dd252788645e940eada959bdde927426e2531c9Paul Duffin    static TypeVariable<?> getTypeVariable(String methodName) throws Exception {
2897dd252788645e940eada959bdde927426e2531c9Paul Duffin      ParameterizedType parameterType = (ParameterizedType)
2907dd252788645e940eada959bdde927426e2531c9Paul Duffin          WithTypeVariable.class
2917dd252788645e940eada959bdde927426e2531c9Paul Duffin              .getDeclaredMethod(methodName, List.class)
2927dd252788645e940eada959bdde927426e2531c9Paul Duffin              .getGenericParameterTypes()[0];
2937dd252788645e940eada959bdde927426e2531c9Paul Duffin      return (TypeVariable<?>) parameterType.getActualTypeArguments()[0];
2947dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
2957dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2967dd252788645e940eada959bdde927426e2531c9Paul Duffin
2977dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewTypeVariable() throws Exception {
2987dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeVariable<?> noBoundJvmType =
2997dd252788645e940eada959bdde927426e2531c9Paul Duffin        WithTypeVariable.getTypeVariable("withoutBound");
3007dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeVariable<?> objectBoundJvmType =
3017dd252788645e940eada959bdde927426e2531c9Paul Duffin        WithTypeVariable.getTypeVariable("withObjectBound");
3027dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeVariable<?> upperBoundJvmType =
3037dd252788645e940eada959bdde927426e2531c9Paul Duffin        WithTypeVariable.getTypeVariable("withUpperBound");
3047dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeVariable<?> noBound = withBounds(noBoundJvmType);
3057dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeVariable<?> objectBound = withBounds(objectBoundJvmType, Object.class);
3067dd252788645e940eada959bdde927426e2531c9Paul Duffin    TypeVariable<?> upperBound = withBounds(
3077dd252788645e940eada959bdde927426e2531c9Paul Duffin        upperBoundJvmType, Number.class, CharSequence.class);
3087dd252788645e940eada959bdde927426e2531c9Paul Duffin
3097dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEqualTypeVariable(noBoundJvmType, noBound);
3107dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEqualTypeVariable(noBoundJvmType,
3117dd252788645e940eada959bdde927426e2531c9Paul Duffin        withBounds(noBoundJvmType, Object.class));
3127dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEqualTypeVariable(objectBoundJvmType, objectBound);
3137dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEqualTypeVariable(upperBoundJvmType, upperBound);
3147dd252788645e940eada959bdde927426e2531c9Paul Duffin
3150888a09821a98ac0680fad765217302858e70fa4Paul Duffin    new TypeVariableEqualsTester()
3167dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(noBoundJvmType, noBound)
3177dd252788645e940eada959bdde927426e2531c9Paul Duffin        .addEqualityGroup(objectBoundJvmType, objectBound)
3180888a09821a98ac0680fad765217302858e70fa4Paul Duffin        .addEqualityGroup(upperBoundJvmType, upperBound)
3197dd252788645e940eada959bdde927426e2531c9Paul Duffin        .testEquals();
3207dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3217dd252788645e940eada959bdde927426e2531c9Paul Duffin
3227dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewTypeVariable_primitiveTypeBound() {
3237dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
3240888a09821a98ac0680fad765217302858e70fa4Paul Duffin      Types.newArtificialTypeVariable(List.class, "E", int.class);
3257dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
3267dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (IllegalArgumentException expected) {}
3277dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3287dd252788645e940eada959bdde927426e2531c9Paul Duffin
3297dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewTypeVariable_serializable() throws Exception {
3307dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
3310888a09821a98ac0680fad765217302858e70fa4Paul Duffin      SerializableTester.reserialize(Types.newArtificialTypeVariable(List.class, "E"));
3327dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
3337dd252788645e940eada959bdde927426e2531c9Paul Duffin    } catch (RuntimeException expected) {}
3347dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3357dd252788645e940eada959bdde927426e2531c9Paul Duffin
3367dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static <D extends GenericDeclaration> TypeVariable<D> withBounds(
3377dd252788645e940eada959bdde927426e2531c9Paul Duffin      TypeVariable<D> typeVariable, Type... bounds) {
3380888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return Types.newArtificialTypeVariable(
3397dd252788645e940eada959bdde927426e2531c9Paul Duffin        typeVariable.getGenericDeclaration(), typeVariable.getName(), bounds);
3407dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3417dd252788645e940eada959bdde927426e2531c9Paul Duffin
3420888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static class TypeVariableEqualsTester {
3430888a09821a98ac0680fad765217302858e70fa4Paul Duffin    private final EqualsTester tester = new EqualsTester();
3440888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3450888a09821a98ac0680fad765217302858e70fa4Paul Duffin    TypeVariableEqualsTester addEqualityGroup(Type jvmType, Type... types) {
3460888a09821a98ac0680fad765217302858e70fa4Paul Duffin      if (Types.NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) {
3470888a09821a98ac0680fad765217302858e70fa4Paul Duffin        tester.addEqualityGroup(jvmType);
3480888a09821a98ac0680fad765217302858e70fa4Paul Duffin        tester.addEqualityGroup((Object[]) types);
3490888a09821a98ac0680fad765217302858e70fa4Paul Duffin      } else {
3500888a09821a98ac0680fad765217302858e70fa4Paul Duffin        tester.addEqualityGroup(Lists.asList(jvmType, types).toArray());
3510888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
3520888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return this;
3530888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
3540888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    void testEquals() {
3560888a09821a98ac0680fad765217302858e70fa4Paul Duffin      tester.testEquals();
3570888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
3580888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3590888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3607dd252788645e940eada959bdde927426e2531c9Paul Duffin  private static void assertEqualTypeVariable(
3617dd252788645e940eada959bdde927426e2531c9Paul Duffin      TypeVariable<?> expected, TypeVariable<?> actual) {
3627dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(expected.toString(), actual.toString());
3637dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(expected.getName(), actual.getName());
3647dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(
3657dd252788645e940eada959bdde927426e2531c9Paul Duffin        expected.getGenericDeclaration(), actual.getGenericDeclaration());
3660888a09821a98ac0680fad765217302858e70fa4Paul Duffin    if (!Types.NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) {
3670888a09821a98ac0680fad765217302858e70fa4Paul Duffin      assertEquals(actual.toString(), expected.hashCode(), actual.hashCode());
3680888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
3690888a09821a98ac0680fad765217302858e70fa4Paul Duffin    ASSERT.that(actual.getBounds()).has().exactlyAs(asList(expected.getBounds())).inOrder();
3707dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3717dd252788645e940eada959bdde927426e2531c9Paul Duffin
3727dd252788645e940eada959bdde927426e2531c9Paul Duffin  /**
3737dd252788645e940eada959bdde927426e2531c9Paul Duffin   * Working with arrays requires defensive code. Verify that we clone the
3747dd252788645e940eada959bdde927426e2531c9Paul Duffin   * type array for both input and output.
3757dd252788645e940eada959bdde927426e2531c9Paul Duffin   */
3767dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedTypeImmutability() {
3777dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type[] typesIn = { String.class, Integer.class };
3787dd252788645e940eada959bdde927426e2531c9Paul Duffin    ParameterizedType parameterizedType
3797dd252788645e940eada959bdde927426e2531c9Paul Duffin        = Types.newParameterizedType(Map.class, typesIn);
3807dd252788645e940eada959bdde927426e2531c9Paul Duffin    typesIn[0] = null;
3817dd252788645e940eada959bdde927426e2531c9Paul Duffin    typesIn[1] = null;
3827dd252788645e940eada959bdde927426e2531c9Paul Duffin
3837dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type[] typesOut = parameterizedType.getActualTypeArguments();
3847dd252788645e940eada959bdde927426e2531c9Paul Duffin    typesOut[0] = null;
3857dd252788645e940eada959bdde927426e2531c9Paul Duffin    typesOut[1] = null;
3867dd252788645e940eada959bdde927426e2531c9Paul Duffin
3877dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]);
3887dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(Integer.class, parameterizedType.getActualTypeArguments()[1]);
3897dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3907dd252788645e940eada959bdde927426e2531c9Paul Duffin
3917dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNewParameterizedTypeWithWrongNumberOfTypeArguments() {
3927dd252788645e940eada959bdde927426e2531c9Paul Duffin    try {
3937dd252788645e940eada959bdde927426e2531c9Paul Duffin      Types.newParameterizedType(
3947dd252788645e940eada959bdde927426e2531c9Paul Duffin          Map.class, String.class, Integer.class, Long.class);
3957dd252788645e940eada959bdde927426e2531c9Paul Duffin      fail();
3960888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (IllegalArgumentException expected) {}
3977dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
3987dd252788645e940eada959bdde927426e2531c9Paul Duffin
3997dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testToString() {
4007dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(int[].class.getName(), Types.toString(int[].class));
4017dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(int[][].class.getName(), Types.toString(int[][].class));
4027dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(String[].class.getName(), Types.toString(String[].class));
4037dd252788645e940eada959bdde927426e2531c9Paul Duffin    Type elementType = List.class.getTypeParameters()[0];
4047dd252788645e940eada959bdde927426e2531c9Paul Duffin    assertEquals(elementType.toString(), Types.toString(elementType));
4057dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4067dd252788645e940eada959bdde927426e2531c9Paul Duffin
4077dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void testNullPointers() {
4087dd252788645e940eada959bdde927426e2531c9Paul Duffin    new NullPointerTester().testStaticMethods(Types.class, Visibility.PACKAGE);
4097dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
4107dd252788645e940eada959bdde927426e2531c9Paul Duffin}
411