View Javadoc

1   /*
2    * Grapht, an open source dependency injector.
3    * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
4    * Copyright 2010-2014 Regents of the University of Minnesota
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation; either version 2.1 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14   * details.
15   *
16   * You should have received a copy of the GNU General Public License along with
17   * this program; if not, write to the Free Software Foundation, Inc., 51
18   * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19   */
20  package org.grouplens.grapht.util;
21  
22  import org.grouplens.grapht.reflect.internal.types.InterfaceA;
23  import org.grouplens.grapht.reflect.internal.types.InterfaceB;
24  import org.grouplens.grapht.reflect.internal.types.TypeA;
25  import org.grouplens.grapht.reflect.internal.types.TypeB;
26  import org.hamcrest.CoreMatchers;
27  import org.junit.Test;
28  
29  import javax.inject.Provider;
30  import java.io.InputStream;
31  import java.lang.reflect.Field;
32  import java.lang.reflect.ParameterizedType;
33  import java.lang.reflect.Type;
34  import java.lang.reflect.WildcardType;
35  import java.util.AbstractList;
36  import java.util.ArrayList;
37  import java.util.List;
38  
39  import static org.hamcrest.CoreMatchers.equalTo;
40  import static org.junit.Assert.assertThat;
41  import static org.junit.Assert.fail;
42  
43  @SuppressWarnings("rawtypes")
44  public class TypesTest {
45      @Test
46      public void testEraseClass() {
47          assertThat(Types.erase(String.class),
48                  equalTo((Class) String.class));
49      }
50  
51      @Test
52      public void testEraseParamType() {
53          assertThat(Types.erase(ArrayList.class.getGenericSuperclass()), equalTo((Class) AbstractList.class));
54      }
55  
56      @Test(expected = IllegalArgumentException.class)
57      public void testEraseVariable() {
58          Type var = List.class.getTypeParameters()[0];
59          Types.erase(var);
60      }
61  
62      @Test(expected = IllegalArgumentException.class)
63      public void testEraseWildcard() throws NoSuchFieldException {
64          class WildTest {
65              @SuppressWarnings("unused")
66              public List<? extends InputStream> field;
67          }
68  
69          Field field = WildTest.class.getField("field");
70          Type ft = field.getGenericType();
71          assertThat(Types.erase(ft), equalTo((Class) List.class));
72          ParameterizedType pft = (ParameterizedType) ft;
73          Type param = pft.getActualTypeArguments()[0];
74          assertThat(param, CoreMatchers.instanceOf(WildcardType.class));
75          // finally, throw an illegal argument exception
76          Types.erase(param);
77      }
78  
79      private void testProvidedType(Class<? extends Provider<?>> cls){
80          Class<?> result = Types.getProvidedType(TestingProviders.SimpleProvider.class);
81          assertThat(result, equalTo((Class) TestingProviders.Target.class));
82      }
83  
84      @Test
85      public void testSimpleProvider(){
86          testProvidedType(TestingProviders.SimpleProvider.class);
87      }
88  
89      @Test
90      public void testAbstractProvider(){
91          testProvidedType(TestingProviders.SubtypedProvider.class);
92          testProvidedType(TestingProviders.SubtypedProvider2.class);
93      }
94  
95      @Test
96      public void testInterfaceProvider(){
97          testProvidedType(TestingProviders.ImplementedProvider.class);
98          testProvidedType(TestingProviders.ImplementedProvider2.class);
99      }
100 
101     @Test
102     public void testBoundedProvider(){
103         Class<?> cls = new TestingProviders.BoundedProvider<TestingProviders.Target>().getClass();
104         try{
105             Types.getProvidedType((Class<? extends Provider<?>>) cls);
106             fail("getProvidedType didn't throw an IllegalArgumentException");
107         }
108         catch (IllegalArgumentException e){
109             // This is the correct behavior
110         }
111         cls = new TestingProviders.UnboundedProvider<TestingProviders.Target>().getClass();
112         try{
113             Types.getProvidedType((Class<? extends Provider<?>>) cls);
114             fail("getProvidedType didn't throw an IllegalArgumentException");
115         }
116         catch (IllegalArgumentException e){
117             // This is the correct behavior
118         }
119     }
120 
121     @Test
122     public void testMultiBoundProvider(){
123         Class<?> cls = new TestingProviders.MultiBoundProvider<TestingProviders.Target>().getClass();
124         try{
125             Types.getProvidedType((Class<? extends Provider<?>>) cls);
126             fail("getProvidedType didn't throw an IllegalArgumentException");
127         }
128         catch (IllegalArgumentException e){
129             // This is the correct behavior
130         }
131     }
132 
133     @Test
134     public void testSameClassDistance() {
135         assertThat(Types.getTypeDistance(String.class, String.class),
136                    equalTo(0));
137     }
138 
139     @Test
140     public void testSubClassDistance() {
141         assertThat(Types.getTypeDistance(TypeB.class, TypeA.class),
142                    equalTo(1));
143     }
144 
145     @Test
146     public void testInterfaceDistance() {
147         assertThat(Types.getTypeDistance(TypeA.class, InterfaceA.class),
148                    equalTo(1));
149     }
150 
151     @Test
152     public void testTwoStepInterfaceDistance() {
153         assertThat(Types.getTypeDistance(TypeB.class, InterfaceA.class),
154                    equalTo(2));
155     }
156 
157     @Test
158     public void testSecondInterfaceDistance() {
159         assertThat(Types.getTypeDistance(TypeB.class, InterfaceB.class),
160                    equalTo(1));
161     }
162 
163     @Test
164     public void testTypedProvider() {
165         Provider<String> string = Providers.of("string");
166         assertThat(Types.getProvidedType(string),
167                    equalTo((Class) String.class));
168     }
169 
170     /**
171      * Test that the most specific type is retrieved when the inferred type is more specific
172      * than the observed type.
173      */
174     @Test
175     public void testProvidedTypeCheckInferred() {
176         Provider<String> string = new NastyStringProvider("foo");
177         assertThat(Types.getProvidedType(string),
178                    equalTo((Class) String.class));
179     }
180 
181     @Test
182     public void testBadTypeDistance() {
183         try {
184             Types.getTypeDistance(TypeB.class, String.class);
185             fail("type distance on bad type should throw exception");
186         } catch (IllegalArgumentException e) {
187             /* expected */
188         }
189     }
190 
191     public static class Inner {}
192 
193     private static class UntypedInstProv<T> implements Provider<T> {
194         private final T instance;
195 
196         public UntypedInstProv(T inst){
197             instance = inst;
198         }
199 
200         @Override
201         public T get() {
202             return instance;
203         }
204     }
205 
206     private static class NastyStringProvider extends UntypedInstProv<String> {
207         public NastyStringProvider(String foo) {
208             super(foo);
209         }
210     }
211 }