Home | History | Annotate | Download | only in util
      1 /**
      2  * Copyright (C) 2008 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 package com.google.inject.util;
     19 
     20 import static com.google.inject.Asserts.assertContains;
     21 import static com.google.inject.Asserts.assertEqualWhenReserialized;
     22 import static com.google.inject.Asserts.assertEqualsBothWays;
     23 import static com.google.inject.util.Types.subtypeOf;
     24 import static com.google.inject.util.Types.supertypeOf;
     25 
     26 import com.google.inject.TypeLiteral;
     27 import com.google.inject.internal.MoreTypes;
     28 
     29 import junit.framework.Assert;
     30 import junit.framework.TestCase;
     31 
     32 import java.io.IOException;
     33 import java.lang.reflect.GenericArrayType;
     34 import java.lang.reflect.ParameterizedType;
     35 import java.lang.reflect.Type;
     36 import java.lang.reflect.WildcardType;
     37 import java.util.List;
     38 import java.util.Map;
     39 import java.util.Set;
     40 
     41 /**
     42  * @author jessewilson (at) google.com (Jesse Wilson)
     43  */
     44 public class TypesTest extends TestCase {
     45 
     46   // generic types for comparison
     47   Map<String, Integer> a;
     48   Inner<Float, Double> b;
     49   List<Set<String>[][]> c;
     50   List<String> d;
     51   Set<String> e;
     52   Outer<String>.Inner f;
     53 
     54   private ParameterizedType mapStringInteger;
     55   private ParameterizedType innerFloatDouble;
     56   private ParameterizedType listSetStringArray;
     57   private ParameterizedType listString;
     58   private ParameterizedType setString;
     59   private ParameterizedType outerInner;
     60   private GenericArrayType setStringArray;
     61 
     62   @Override
     63   protected void setUp() throws Exception {
     64     super.setUp();
     65     mapStringInteger = (ParameterizedType) getClass().getDeclaredField("a").getGenericType();
     66     innerFloatDouble = (ParameterizedType) getClass().getDeclaredField("b").getGenericType();
     67     listSetStringArray = (ParameterizedType) getClass().getDeclaredField("c").getGenericType();
     68     listString = (ParameterizedType) getClass().getDeclaredField("d").getGenericType();
     69     setString = (ParameterizedType) getClass().getDeclaredField("e").getGenericType();
     70     outerInner = (ParameterizedType) getClass().getDeclaredField("f").getGenericType();
     71     setStringArray = (GenericArrayType) listSetStringArray.getActualTypeArguments()[0];
     72   }
     73 
     74   public void testListSetMap() {
     75     assertEqualsBothWays(mapStringInteger, Types.mapOf(String.class, Integer.class));
     76     assertEqualsBothWays(listString, Types.listOf(String.class));
     77     assertEqualsBothWays(setString, Types.setOf(String.class));
     78   }
     79 
     80   public void testDefensiveCopies() {
     81     Type[] arguments = new Type[] { String.class, Integer.class };
     82     ParameterizedType parameterizedType = Types.newParameterizedType(Map.class, arguments);
     83     arguments[0] = null;
     84     assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]);
     85     parameterizedType.getActualTypeArguments()[1] = null;
     86     assertEquals(Integer.class, parameterizedType.getActualTypeArguments()[1]);
     87   }
     88 
     89   public void testTypeWithOwnerType() {
     90     ParameterizedType actual = Types.newParameterizedTypeWithOwner(
     91         TypesTest.class, Inner.class, Float.class, Double.class);
     92     assertEquals(TypesTest.class, actual.getOwnerType());
     93     assertEqualsBothWays(innerFloatDouble, actual);
     94     // The JDK prints this out as:
     95     //     com.google.inject.util.TypesTest.com.google.inject.util.TypesTest$Inner<java.lang.Float, java.lang.Double>
     96     // and we think that's wrong, so the assertEquals comparison is worthless. :-(
     97 //    assertEquals(innerFloatDouble.toString(), actual.toString());
     98 
     99     // We think the correct comparison is:
    100     assertEquals("com.google.inject.util.TypesTest$Inner<java.lang.Float, java.lang.Double>", actual.toString());
    101   }
    102 
    103   public void testTypeParametersMustNotBePrimitives() {
    104     try {
    105       Types.newParameterizedType(Map.class, String.class, int.class);
    106       fail();
    107     } catch (IllegalArgumentException expected) {
    108       assertContains(expected.getMessage(),
    109           "Primitive types are not allowed in type parameters: int");
    110     }
    111   }
    112 
    113   public List<? extends CharSequence> wildcardExtends;
    114   public List<? super CharSequence> wildcardSuper;
    115   public List<?> wildcardObject;
    116 
    117   public void testWildcardTypes() throws NoSuchFieldException, IOException {
    118     assertEqualsBothWays(getWildcard("wildcardSuper"), supertypeOf(CharSequence.class));
    119     assertEqualsBothWays(getWildcard("wildcardExtends"), subtypeOf(CharSequence.class));
    120     assertEqualsBothWays(getWildcard("wildcardObject"), subtypeOf(Object.class));
    121 
    122     assertEquals("? super java.lang.CharSequence", supertypeOf(CharSequence.class).toString());
    123     assertEquals("? extends java.lang.CharSequence", subtypeOf(CharSequence.class).toString());
    124     assertEquals("?", subtypeOf(Object.class).toString());
    125 
    126     assertEqualWhenReserialized(supertypeOf(CharSequence.class));
    127     assertEqualWhenReserialized(subtypeOf(CharSequence.class));
    128   }
    129 
    130   public void testWildcardBoundsMustNotBePrimitives() {
    131     try {
    132       supertypeOf(int.class);
    133       fail();
    134     } catch (IllegalArgumentException expected) {
    135       assertContains(expected.getMessage(),
    136           "Primitive types are not allowed in wildcard bounds: int");
    137     }
    138 
    139     try {
    140       subtypeOf(int.class);
    141       fail();
    142     } catch (IllegalArgumentException expected) {
    143       assertContains(expected.getMessage(),
    144           "Primitive types are not allowed in wildcard bounds: int");
    145     }
    146   }
    147 
    148   private WildcardType getWildcard(String fieldName) throws NoSuchFieldException {
    149     ParameterizedType type = (ParameterizedType) getClass().getField(fieldName).getGenericType();
    150     return (WildcardType) type.getActualTypeArguments()[0];
    151   }
    152 
    153   public void testEqualsAndHashcode() {
    154     ParameterizedType parameterizedType
    155         = Types.newParameterizedType(Map.class, String.class, Integer.class);
    156     assertEqualsBothWays(mapStringInteger, parameterizedType);
    157     assertEquals(mapStringInteger.toString(), parameterizedType.toString());
    158 
    159     GenericArrayType genericArrayType = Types.arrayOf(Types.arrayOf(
    160         Types.newParameterizedType(Set.class, String.class)));
    161     assertEqualsBothWays(setStringArray, genericArrayType);
    162     assertEquals(setStringArray.toString(), genericArrayType.toString());
    163   }
    164 
    165   public void testToString() {
    166     Assert.assertEquals("java.lang.String", MoreTypes.typeToString(String.class));
    167     assertEquals("java.util.Set<java.lang.String>[][]", MoreTypes.typeToString(setStringArray));
    168     assertEquals("java.util.Map<java.lang.String, java.lang.Integer>",
    169         MoreTypes.typeToString(mapStringInteger));
    170     assertEquals("java.util.List<java.util.Set<java.lang.String>[][]>",
    171         MoreTypes.typeToString(listSetStringArray));
    172     assertEquals(innerFloatDouble.toString(),
    173         MoreTypes.typeToString(innerFloatDouble));
    174   }
    175 
    176   static class Owning<A> {}
    177 
    178   /**
    179    * Ensure that owning types are required when necessary, and forbidden
    180    * otherwise.
    181    */
    182   public void testCanonicalizeRequiresOwnerTypes() {
    183     try {
    184       Types.newParameterizedType(Owning.class, String.class);
    185       fail();
    186     } catch (IllegalArgumentException expected) {
    187       assertContains(expected.getMessage(),
    188           "No owner type for enclosed " + Owning.class);
    189     }
    190 
    191     try {
    192       Types.newParameterizedTypeWithOwner(Object.class, Set.class, String.class);
    193     } catch (IllegalArgumentException expected) {
    194       assertContains(expected.getMessage(),
    195           "Owner type for unenclosed " + Set.class);
    196     }
    197   }
    198 
    199   @SuppressWarnings("UnusedDeclaration")
    200   class Inner<T1, T2> {}
    201 
    202   public void testInnerParameterizedEvenWithZeroArgs() {
    203     TypeLiteral<Outer<String>.Inner> type = new TypeLiteral<Outer<String>.Inner>() {};
    204     assertEqualsBothWays(outerInner, type.getType());
    205 
    206     ParameterizedType parameterizedType = (ParameterizedType) type.getType();
    207     assertEquals(0, parameterizedType.getActualTypeArguments().length);
    208     assertEquals(new TypeLiteral<Outer<String>>() {}.getType(), parameterizedType.getOwnerType());
    209     assertEquals(Outer.Inner.class, parameterizedType.getRawType());
    210   }
    211 
    212   static class Outer<T> {
    213     class Inner {}
    214   }
    215 }
    216