/* * Copyright (C) 2007 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.reflect; import static org.truth0.Truth.ASSERT; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.common.primitives.Primitives; import com.google.common.testing.EqualsTester; import com.google.common.testing.NullPointerTester; import com.google.common.testing.SerializableTester; import junit.framework.TestCase; import org.truth0.subjects.CollectionSubject; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; /** * Test cases for {@link TypeToken}. * * @author Sven Mawson * @author Ben Yu */ public class TypeTokenTest extends TestCase { private abstract static class StringList implements List {} private abstract static class IntegerList implements List {} public void testValueEqualityNotInstanceEquality() { TypeToken> a = new TypeToken>() {}; TypeToken> b = new TypeToken>() {}; assertEquals(a, b); } public void testVariableTypeTokenNotAllowed() { try { new TypeToken() {}; fail(); } catch (IllegalStateException expected) {} } public void testRawTypeIsCorrect() { TypeToken> token = new TypeToken>() {}; assertEquals(List.class, token.getRawType()); } public void testTypeIsCorrect() { TypeToken> token = new TypeToken>() {}; assertEquals(StringList.class.getGenericInterfaces()[0], token.getType()); } @SuppressWarnings("rawtypes") // Trying to test TypeToken.of(List.class) public void testGetClass() { TypeToken token = TypeToken.of(List.class); assertEquals(new TypeToken() {}, token); } public void testGetType() { TypeToken t = TypeToken.of(StringList.class.getGenericInterfaces()[0]); assertEquals(new TypeToken>() {}, t); } public void testNonStaticLocalClass() { class Local {} TypeToken> type = new TypeToken>() {}; assertEquals(Types.newParameterizedType(Local.class, String.class), type.getType()); assertEquals(new Local() {}.getClass().getGenericSuperclass(), type.getType()); } public void testStaticLocalClass() { doTestStaticLocalClass(); } private static void doTestStaticLocalClass() { class Local {} TypeToken> type = new TypeToken>() {}; assertEquals(Types.newParameterizedType(Local.class, String.class), type.getType()); assertEquals(new Local() {}.getClass().getGenericSuperclass(), type.getType()); } public void testGenericArrayType() throws Exception { TypeToken[]> token = new TypeToken[]>() {}; assertEquals(List[].class, token.getRawType()); assertTrue(token.getType() instanceof GenericArrayType); } public void testMultiDimensionalGenericArrayType() throws Exception { TypeToken[][][]> token = new TypeToken[][][]>() {}; assertEquals(List[][][].class, token.getRawType()); assertTrue(token.getType() instanceof GenericArrayType); } public void testGenericVariableTypeArrays() throws Exception { assertEquals("T[]", new TypeToken() {}.toString()); } public void testResolveType() throws Exception { Method getFromList = List.class.getMethod("get", int.class); TypeToken returnType = new TypeToken>() {} .resolveType(getFromList.getGenericReturnType()); assertEquals(String.class, returnType.getType()); } public & Function & Iterable> void testResolveType_fromTypeVariable() throws Exception { TypeToken f = TypeToken.of(new TypeCapture() {}.capture()); assertEquals(String.class, f.resolveType(Function.class.getTypeParameters()[0]).getType()); assertEquals(Integer.class, f.resolveType(Function.class.getTypeParameters()[1]).getType()); assertEquals(Long.class, f.resolveType(Iterable.class.getTypeParameters()[0]).getType()); } public > & Iterable> void testResolveType_fromTypeVariable_onlyDirectBoundsAreUsed() throws Exception { TypeToken e = TypeToken.of(new TypeCapture() {}.capture()); assertEquals(Integer.class, e.resolveType(Iterable.class.getTypeParameters()[0]).getType()); } public void testResolveType_fromWildcard() throws Exception { ParameterizedType withWildcardType = (ParameterizedType) new TypeCapture>>() {}.capture(); TypeToken wildcardType = TypeToken.of(withWildcardType.getActualTypeArguments()[0]); assertEquals(String.class, wildcardType.resolveType(Iterable.class.getTypeParameters()[0]).getType()); } public void testGetTypes_noSuperclass() { TypeToken.TypeSet types = new TypeToken() {}.getTypes(); ASSERT.that(types).has().item(TypeToken.of(Object.class)); ASSERT.that(types.rawTypes()).has().item(Object.class); ASSERT.that(types.interfaces()).isEmpty(); ASSERT.that(types.interfaces().rawTypes()).isEmpty(); ASSERT.that(types.classes()).has().item(TypeToken.of(Object.class)); ASSERT.that(types.classes().rawTypes()).has().item(Object.class); } public void testGetTypes_fromInterface() { TypeToken.TypeSet types = new TypeToken() {}.getTypes(); ASSERT.that(types).has().item(TypeToken.of(Interface1.class)); ASSERT.that(types.rawTypes()).has().item(Interface1.class); ASSERT.that(types.interfaces()).has().item(TypeToken.of(Interface1.class)); ASSERT.that(types.interfaces().rawTypes()).has().item(Interface1.class); ASSERT.that(types.classes()).isEmpty(); ASSERT.that(types.classes().rawTypes()).isEmpty(); } public void testGetTypes_fromPrimitive() { TypeToken.TypeSet types = TypeToken.of(int.class).getTypes(); ASSERT.that(types).has().item(TypeToken.of(int.class)); ASSERT.that(types.rawTypes()).has().item(int.class); ASSERT.that(types.interfaces()).isEmpty(); ASSERT.that(types.interfaces().rawTypes()).isEmpty(); ASSERT.that(types.classes()).has().item(TypeToken.of(int.class)); ASSERT.that(types.classes().rawTypes()).has().item(int.class); } public void testGetTypes_withInterfacesAndSuperclasses() { abstract class Class2 extends Class1 implements Interface12 {} abstract class Class3 extends Class2 implements Interface3 {} TypeToken>.TypeSet types = new TypeToken>() {}.getTypes(); assertThat(types).has().exactly( new TypeToken>() {}, new TypeToken>() {}, new TypeToken>() {}, TypeToken.of(Class2.class), TypeToken.of(Interface12.class), TypeToken.of(Interface1.class), TypeToken.of(Interface2.class), TypeToken.of(Class1.class), TypeToken.of(Object.class)); assertThat(types.interfaces()).has().exactly( new TypeToken>() {}, TypeToken.of(Interface12.class), TypeToken.of(Interface1.class), TypeToken.of(Interface2.class), new TypeToken>() {}); assertThat(types.classes()).has().exactly( new TypeToken>() {}, TypeToken.of(Class2.class), TypeToken.of(Class1.class), TypeToken.of(Object.class)); assertSubtypeFirst(types); } public void testGetTypes_rawTypes_withInterfacesAndSuperclasses() { abstract class Class2 extends Class1 implements Interface12 {} abstract class Class3 extends Class2 implements Interface3 {} TypeToken>.TypeSet types = new TypeToken>() {}.getTypes(); assertThat(types.rawTypes()).has().exactly( Class3.class, Interface3.class, Iterable.class, Class2.class, Interface12.class, Interface1.class, Interface2.class, Class1.class, Object.class); assertThat(types.interfaces().rawTypes()).has().exactly( Interface3.class, Interface12.class, Interface1.class, Interface2.class, Iterable.class); assertThat(types.classes().rawTypes()).has().exactly( Class3.class, Class2.class, Class1.class, Object.class); assertSubtypeFirst(types); } public void testGetTypes_ignoresTypeVariablesByDefault() { TypeToken.TypeSet types = TypeToken.of(new TypeCapture() {}.capture()).getTypes(); assertThat(types).has().exactly( TypeToken.of(Interface1.class), TypeToken.of(Class1.class), TypeToken.of(Object.class)); assertSubtypeFirst(types); assertThat(types.interfaces()) .has().exactly(TypeToken.of(Interface1.class)) .inOrder(); assertThat(types.classes()) .has().exactly(TypeToken.of(Class1.class), TypeToken.of(Object.class)) .inOrder(); } public void testGetTypes_rawTypes_ignoresTypeVariablesByDefault() { TypeToken.TypeSet types = TypeToken.of(new TypeCapture() {}.capture()).getTypes(); assertThat(types.rawTypes()) .has().exactly(Interface1.class, Class1.class, Object.class); assertThat(types.interfaces().rawTypes()) .has().exactly(Interface1.class) .inOrder(); assertThat(types.classes().rawTypes()) .has().exactly(Class1.class, Object.class) .inOrder(); } public > void testGetTypes_manyBounds() { TypeToken.TypeSet types = TypeToken.of(new TypeCapture() {}.capture()).getTypes(); assertThat(types.rawTypes()) .has().exactly(Interface1.class, Interface2.class, Interface3.class, Iterable.class); } private static void assertSubtypeFirst(TypeToken.TypeSet types) { assertSubtypeTokenBeforeSupertypeToken(types); assertSubtypeTokenBeforeSupertypeToken(types.interfaces()); assertSubtypeTokenBeforeSupertypeToken(types.classes()); assertSubtypeBeforeSupertype(types.rawTypes()); assertSubtypeBeforeSupertype(types.interfaces().rawTypes()); assertSubtypeBeforeSupertype(types.classes().rawTypes()); } private static void assertSubtypeTokenBeforeSupertypeToken( Iterable> types) { int i = 0; for (TypeToken left : types) { int j = 0; for (TypeToken right : types) { if (left.isAssignableFrom(right)) { assertTrue(left + " should be after " + right, i >= j); } j++; } i++; } } private static void assertSubtypeBeforeSupertype(Iterable> types) { int i = 0; for (Class left : types) { int j = 0; for (Class right : types) { if (left.isAssignableFrom(right)) { assertTrue(left + " should be after " + right, i >= j); } j++; } i++; } } // Tests to make sure assertSubtypeBeforeSupertype() works. public void testAssertSubtypeTokenBeforeSupertypeToken_empty() { assertSubtypeTokenBeforeSupertypeToken(ImmutableList.>of()); } public void testAssertSubtypeTokenBeforeSupertypeToken_oneType() { assertSubtypeTokenBeforeSupertypeToken(ImmutableList.of(TypeToken.of(String.class))); } public void testAssertSubtypeTokenBeforeSupertypeToken_subtypeFirst() { assertSubtypeTokenBeforeSupertypeToken( ImmutableList.of(TypeToken.of(String.class), TypeToken.of(CharSequence.class))); } public void testAssertSubtypeTokenBeforeSupertypeToken_supertypeFirst() { try { assertSubtypeTokenBeforeSupertypeToken( ImmutableList.of(TypeToken.of(CharSequence.class), TypeToken.of(String.class))); } catch (AssertionError expected) { return; } fail(); } public void testAssertSubtypeTokenBeforeSupertypeToken_duplicate() { try { assertSubtypeTokenBeforeSupertypeToken( ImmutableList.of(TypeToken.of(String.class), TypeToken.of(String.class))); } catch (AssertionError expected) { return; } fail(); } public void testAssertSubtypeBeforeSupertype_empty() { assertSubtypeBeforeSupertype(ImmutableList.>of()); } public void testAssertSubtypeBeforeSupertype_oneType() { assertSubtypeBeforeSupertype(ImmutableList.of(String.class)); } public void testAssertSubtypeBeforeSupertype_subtypeFirst() { assertSubtypeBeforeSupertype( ImmutableList.of(String.class, CharSequence.class)); } public void testAssertSubtypeBeforeSupertype_supertypeFirst() { try { assertSubtypeBeforeSupertype( ImmutableList.of(CharSequence.class, String.class)); } catch (AssertionError expected) { return; } fail(); } public void testAssertSubtypeBeforeSupertype_duplicate() { try { assertSubtypeBeforeSupertype( ImmutableList.of(String.class, String.class)); } catch (AssertionError expected) { return; } fail(); } public void testGetGenericSuperclass_noSuperclass() { assertNull(new TypeToken() {}.getGenericSuperclass()); assertEquals(TypeToken.of(Object.class), new TypeToken() {}.getGenericSuperclass()); assertNull(new TypeToken>() {}.getGenericSuperclass()); assertEquals(TypeToken.of(Object.class), new TypeToken[]>() {}.getGenericSuperclass()); } public void testGetGenericSuperclass_withSuperclass() { TypeToken> superToken = new TypeToken>() {}.getGenericSuperclass(); assertEquals(ArrayList.class.getSuperclass(), superToken.getRawType()); assertEquals(String.class, ((ParameterizedType) superToken.getType()).getActualTypeArguments()[0]); assertEquals(TypeToken.of(Base.class), TypeToken.of(Sub.class).getGenericSuperclass()); assertEquals(TypeToken.of(Object.class), TypeToken.of(Sub[].class).getGenericSuperclass()); } public void testGetGenericSuperclass_typeVariable_unbounded() { assertEquals(TypeToken.of(Object.class), TypeToken.of(new TypeCapture() {}.capture()).getGenericSuperclass()); assertEquals(TypeToken.of(Object.class), new TypeToken() {}.getGenericSuperclass()); } public & CharSequence> void testGetGenericSuperclass_typeVariable_boundIsClass() { assertEquals(new TypeToken>() {}, TypeToken.of(new TypeCapture() {}.capture()).getGenericSuperclass()); assertEquals(TypeToken.of(Object.class), new TypeToken() {}.getGenericSuperclass()); } public & CharSequence> void testGetGenericSuperclass_typeVariable_boundIsFBoundedClass() { assertEquals(new TypeToken>() {}, TypeToken.of(new TypeCapture() {}.capture()).getGenericSuperclass()); assertEquals(TypeToken.of(Object.class), new TypeToken() {}.getGenericSuperclass()); } public & CharSequence> void testGetGenericSuperclass_typeVariable_boundIsInterface() { assertNull(TypeToken.of(new TypeCapture() {}.capture()).getGenericSuperclass()); assertEquals(TypeToken.of(Object.class), new TypeToken() {}.getGenericSuperclass()); } public & CharSequence, T1 extends T> void testGetGenericSuperclass_typeVariable_boundIsTypeVariableAndClass() { assertEquals(TypeToken.of(new TypeCapture() {}.capture()), TypeToken.of(new TypeCapture() {}.capture()).getGenericSuperclass()); assertEquals(TypeToken.of(Object.class), new TypeToken() {}.getGenericSuperclass()); } public & CharSequence, T1 extends T> void testGetGenericSuperclass_typeVariable_boundIsTypeVariableAndInterface() { assertNull(TypeToken.of(new TypeCapture() {}.capture()).getGenericSuperclass()); assertEquals(TypeToken.of(Object.class), new TypeToken() {}.getGenericSuperclass()); } public void testGetGenericSuperclass_wildcard_lowerBounded() { assertEquals(TypeToken.of(Object.class), TypeToken.of(Types.supertypeOf(String.class)).getGenericSuperclass()); assertEquals(new TypeToken() {}, TypeToken.of(Types.supertypeOf(String[].class)).getGenericSuperclass()); assertEquals(new TypeToken() {}, TypeToken.of(Types.supertypeOf(CharSequence.class)).getGenericSuperclass()); } public void testGetGenericSuperclass_wildcard_boundIsClass() { assertEquals(TypeToken.of(Object.class), TypeToken.of(Types.subtypeOf(Object.class)).getGenericSuperclass()); assertEquals(new TypeToken() {}, TypeToken.of(Types.subtypeOf(Object[].class)).getGenericSuperclass()); } public void testGetGenericSuperclass_wildcard_boundIsInterface() { assertNull(TypeToken.of(Types.subtypeOf(CharSequence.class)).getGenericSuperclass()); assertEquals(new TypeToken() {}, TypeToken.of(Types.subtypeOf(CharSequence[].class)).getGenericSuperclass()); } public void testGetGenericInterfaces_typeVariable_unbounded() { ASSERT.that(TypeToken.of(new TypeCapture() {}.capture()).getGenericInterfaces()).isEmpty(); assertHasArrayInterfaces(new TypeToken() {}); } public void testGetGenericInterfaces_typeVariable_boundIsClass() { ASSERT.that(TypeToken.of(new TypeCapture() {}.capture()).getGenericInterfaces()).isEmpty(); assertHasArrayInterfaces(new TypeToken() {}); } public > void testGetGenericInterfaces_typeVariable_boundsAreClassWithInterface() { assertThat(TypeToken.of(new TypeCapture() {}.capture()).getGenericInterfaces()) .has().exactly(new TypeToken>() {}); assertHasArrayInterfaces(new TypeToken() {}); } public > void testGetGenericInterfaces_typeVariable_boundsAreInterfaces() { assertThat(TypeToken.of(new TypeCapture() {}.capture()).getGenericInterfaces()) .has().exactly(TypeToken.of(CharSequence.class), new TypeToken>() {}); assertHasArrayInterfaces(new TypeToken() {}); } public > void testGetGenericInterfaces_typeVariable_boundsAreFBoundedInterfaces() { assertThat(TypeToken.of(new TypeCapture() {}.capture()).getGenericInterfaces()) .has().exactly(TypeToken.of(CharSequence.class), new TypeToken>() {}); assertHasArrayInterfaces(new TypeToken() {}); } public > void testGetGenericInterfaces_typeVariable_boundsAreClassWithFBoundedInterface() { assertThat(TypeToken.of(new TypeCapture() {}.capture()).getGenericInterfaces()) .has().exactly(new TypeToken>() {}); assertHasArrayInterfaces(new TypeToken() {}); } public void testGetGenericInterfaces_typeVariable_boundIsTypeVariableAndClass() { ASSERT.that(TypeToken.of(new TypeCapture() {}.capture()).getGenericInterfaces()).isEmpty(); assertHasArrayInterfaces(new TypeToken() {}); } public , T1 extends T, T2 extends T1> void testGetGenericInterfaces_typeVariable_boundIsTypeVariableAndInterface() { assertThat(TypeToken.of(new TypeCapture() {}.capture()).getGenericInterfaces()) .has().exactly(TypeToken.of(new TypeCapture() {}.capture())); assertHasArrayInterfaces(new TypeToken() {}); } public void testGetGenericInterfaces_wildcard_lowerBounded() { ASSERT.that(TypeToken.of(Types.supertypeOf(String.class)).getGenericInterfaces()).isEmpty(); ASSERT.that(TypeToken.of(Types.supertypeOf(String[].class)).getGenericInterfaces()).isEmpty(); } public void testGetGenericInterfaces_wildcard_boundIsClass() { ASSERT.that(TypeToken.of(Types.subtypeOf(Object.class)).getGenericInterfaces()).isEmpty(); ASSERT.that(TypeToken.of(Types.subtypeOf(Object[].class)).getGenericInterfaces()).isEmpty(); } public void testGetGenericInterfaces_wildcard_boundIsInterface() { TypeToken> interfaceType = new TypeToken>() {}; assertThat(TypeToken.of(Types.subtypeOf(interfaceType.getType())).getGenericInterfaces()) .has().exactly(interfaceType); assertHasArrayInterfaces(new TypeToken[]>() {}); } public void testGetGenericInterfaces_noInterface() { ASSERT.that(new TypeToken() {}.getGenericInterfaces()).isEmpty(); assertHasArrayInterfaces(new TypeToken() {}); } public void testGetGenericInterfaces_withInterfaces() { Map, Type> interfaceMap = Maps.newHashMap(); for (TypeToken interfaceType: new TypeToken>() {}.getGenericInterfaces()) { interfaceMap.put(interfaceType.getRawType(), interfaceType.getType()); } assertEquals(ImmutableMap.of( Iterable.class, new TypeToken>() {}.getType(), Map.class, new TypeToken>() {}.getType()), interfaceMap); } private interface Interface1 {} private interface Interface2 {} private interface Interface3 extends Iterable {} private interface Interface12 extends Interface1, Interface2 {} private static class Class1 implements Interface1 {} private static final class NoInterface {} private abstract static class Implementation implements Iterable, Map {} private abstract static class First {} private abstract static class Second extends First {} private abstract static class Third extends Second {} private abstract static class Fourth extends Third {} private static class ConcreteIS extends Fourth {} private static class ConcreteSI extends Fourth {} public void testAssignableClassToClass() { @SuppressWarnings("rawtypes") // To test TypeToken TypeToken tokL = new TypeToken() {}; assertTrue(tokL.isAssignableFrom(List.class)); assertTrue(tokL.isAssignableFrom(ArrayList.class)); assertFalse(tokL.isAssignableFrom(List[].class)); TypeToken tokN = new TypeToken() {}; assertTrue(tokN.isAssignableFrom(Number.class)); assertTrue(tokN.isAssignableFrom(Integer.class)); } public void testAssignableParameterizedTypeToObject() { assertTrue(TypeToken.of(Object.class).isAssignableFrom( TypeToken.of(new TypeCapture() {}.capture()))); assertFalse(TypeToken.of(int.class).isAssignableFrom( TypeToken.of(new TypeCapture() {}.capture()))); } public void testAssignableGenericArrayToGenericArray() { assertTrue(new TypeToken() {}.isAssignableFrom(new TypeToken() {})); assertTrue(new TypeToken() {}.isAssignableFrom(new TypeToken() {})); assertFalse(new TypeToken() {}.isAssignableFrom(new TypeToken() {})); } public void testAssignableWildcardBoundedByArrayToArrayClass() throws Exception { Type wildcardType = Types.subtypeOf(Object[].class); assertTrue(TypeToken.of(Object[].class).isAssignableFrom(wildcardType)); assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType)); assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType)); assertFalse(TypeToken.of(int[].class).isAssignableFrom(wildcardType)); } public void testAssignableArrayClassToBoundedWildcard() throws Exception { TypeToken upperBounded = TypeToken.of(Types.subtypeOf(Object[].class)); TypeToken lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class)); assertTrue(upperBounded.isAssignableFrom(Object[].class)); assertTrue(upperBounded.isAssignableFrom(Object[][].class)); assertTrue(upperBounded.isAssignableFrom(String[].class)); assertTrue(lowerBounded.isAssignableFrom(Object[].class)); assertTrue(lowerBounded.isAssignableFrom(Object.class)); assertFalse(lowerBounded.isAssignableFrom(Object[][].class)); assertFalse(lowerBounded.isAssignableFrom(String[].class)); } public void testAssignableWildcardBoundedByIntArrayToArrayClass() throws Exception { Type wildcardType = Types.subtypeOf(int[].class); assertTrue(TypeToken.of(int[].class).isAssignableFrom(wildcardType)); assertTrue(TypeToken.of(Object.class).isAssignableFrom(wildcardType)); assertTrue(TypeToken.of(wildcardType).isAssignableFrom(wildcardType)); assertFalse(TypeToken.of(Object[].class).isAssignableFrom(wildcardType)); } public void testAssignableWildcardToWildcard() throws Exception { TypeToken upperBounded = TypeToken.of(Types.subtypeOf(Object[].class)); TypeToken lowerBounded = TypeToken.of(Types.supertypeOf(Object[].class)); assertFalse(lowerBounded.isAssignableFrom(upperBounded)); assertTrue(lowerBounded.isAssignableFrom(lowerBounded)); assertTrue(upperBounded.isAssignableFrom(upperBounded)); assertFalse(upperBounded.isAssignableFrom(lowerBounded)); } public void testAssignableGenericArrayToArrayClass() { assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken() {})); assertTrue(TypeToken.of(Object[].class).isAssignableFrom(new TypeToken() {})); assertTrue(TypeToken.of(Object[][].class).isAssignableFrom(new TypeToken() {})); } public void testAssignableParameterizedTypeToClass() { @SuppressWarnings("rawtypes") // Trying to test raw class TypeToken tokL = new TypeToken() {}; assertTrue(tokL.isAssignableFrom(StringList.class)); assertTrue(tokL.isAssignableFrom( StringList.class.getGenericInterfaces()[0])); @SuppressWarnings("rawtypes") // Trying to test raw class TypeToken tokS = new TypeToken() {}; assertTrue(tokS.isAssignableFrom(Second.class)); assertTrue(tokS.isAssignableFrom(Third.class.getGenericSuperclass())); } public void testAssignableArrayToClass() throws Exception { @SuppressWarnings("rawtypes") // Trying to test raw class TypeToken tokL = new TypeToken() {}; assertTrue(tokL.isAssignableFrom(List[].class)); assertFalse(tokL.isAssignableFrom(List.class)); @SuppressWarnings("rawtypes") // Trying to test raw class TypeToken tokS = new TypeToken() {}; assertTrue(tokS.isAssignableFrom(Second[].class)); assertTrue(tokS.isAssignableFrom(Third[].class)); } @SuppressWarnings("rawtypes") // Trying to test raw class public void testAssignableTokenToClass() { TypeToken tokL = new TypeToken() {}; assertTrue(tokL.isAssignableFrom(new TypeToken() {})); assertTrue(tokL.isAssignableFrom(new TypeToken>() {})); assertTrue(tokL.isAssignableFrom(new TypeToken>() {})); TypeToken tokS = new TypeToken() {}; assertTrue(tokS.isAssignableFrom(new TypeToken() {})); assertTrue(tokS.isAssignableFrom(new TypeToken() {})); assertTrue(tokS.isAssignableFrom( new TypeToken>() {})); TypeToken tokA = new TypeToken() {}; assertTrue(tokA.isAssignableFrom(new TypeToken() {})); assertTrue(tokA.isAssignableFrom(new TypeToken[]>() {})); assertTrue(tokA.isAssignableFrom(new TypeToken[]>() {})); } public void testAssignableClassToType() { TypeToken> tokenL = new TypeToken>() {}; assertTrue(tokenL.isAssignableFrom(StringList.class)); assertFalse(tokenL.isAssignableFrom(List.class)); TypeToken> tokenF = new TypeToken>() {}; assertTrue(tokenF.isAssignableFrom(ConcreteIS.class)); assertFalse(tokenF.isAssignableFrom(ConcreteSI.class)); } public void testAssignableClassToArrayType() { TypeToken[]> tokenL = new TypeToken[]>() {}; assertTrue(tokenL.isAssignableFrom(StringList[].class)); assertFalse(tokenL.isAssignableFrom(List[].class)); } public void testAssignableParameterizedTypeToType() { TypeToken> tokenL = new TypeToken>() {}; assertTrue(tokenL.isAssignableFrom( StringList.class.getGenericInterfaces()[0])); assertFalse(tokenL.isAssignableFrom( IntegerList.class.getGenericInterfaces()[0])); TypeToken> tokenF = new TypeToken>() {}; assertTrue(tokenF.isAssignableFrom( ConcreteIS.class.getGenericSuperclass())); assertFalse(tokenF.isAssignableFrom( ConcreteSI.class.getGenericSuperclass())); } public void testGenericArrayTypeToArrayType() throws Exception { TypeToken[]> tokL = new TypeToken[]>() {}; TypeToken[]> token = new TypeToken[]>() {}; assertTrue(tokL.isAssignableFrom(tokL.getType())); assertTrue(tokL.isAssignableFrom(token.getType())); } public void testAssignableTokenToType() { TypeToken> tokenL = new TypeToken>() {}; assertTrue(tokenL.isAssignableFrom(new TypeToken>() {})); assertTrue(tokenL.isAssignableFrom(new TypeToken>() {})); assertTrue(tokenL.isAssignableFrom(new TypeToken() {})); TypeToken> tokenF = new TypeToken>() {}; assertTrue(tokenF.isAssignableFrom(new TypeToken>() {})); assertTrue(tokenF.isAssignableFrom( new TypeToken>() {})); assertFalse(tokenF.isAssignableFrom( new TypeToken>() {})); assertTrue(tokenF.isAssignableFrom( new TypeToken>() {})); assertFalse(tokenF.isAssignableFrom( new TypeToken>() {})); assertTrue(tokenF.isAssignableFrom(new TypeToken() {})); assertFalse(tokenF.isAssignableFrom(new TypeToken() {})); } public void testAssignableWithWildcards() { TypeToken unboundedToken = new TypeToken>() {}; TypeToken upperBoundToken = new TypeToken>() {}; TypeToken lowerBoundToken = new TypeToken>() {}; TypeToken concreteToken = new TypeToken>() {}; TypeToken subtypeToken = new TypeToken>() {}; TypeToken supertypeToken = new TypeToken>() {}; List> allTokens = ImmutableList.of( unboundedToken, upperBoundToken, lowerBoundToken, concreteToken, subtypeToken, supertypeToken); for (TypeToken typeToken : allTokens) { assertTrue(typeToken.toString(), unboundedToken.isAssignableFrom(typeToken)); } assertFalse(upperBoundToken.isAssignableFrom(unboundedToken)); assertTrue(upperBoundToken.isAssignableFrom(upperBoundToken)); assertFalse(upperBoundToken.isAssignableFrom(lowerBoundToken)); assertTrue(upperBoundToken.isAssignableFrom(concreteToken)); assertTrue(upperBoundToken.isAssignableFrom(subtypeToken)); assertFalse(upperBoundToken.isAssignableFrom(supertypeToken)); assertFalse(lowerBoundToken.isAssignableFrom(unboundedToken)); assertFalse(lowerBoundToken.isAssignableFrom(upperBoundToken)); assertTrue(lowerBoundToken.isAssignableFrom(lowerBoundToken)); assertTrue(lowerBoundToken.isAssignableFrom(concreteToken)); assertFalse(lowerBoundToken.isAssignableFrom(subtypeToken)); assertTrue(lowerBoundToken.isAssignableFrom(supertypeToken)); for (TypeToken typeToken : allTokens) { assertEquals(typeToken.toString(), typeToken == concreteToken, concreteToken.isAssignableFrom(typeToken)); } for (TypeToken typeToken : allTokens) { assertEquals(typeToken.toString(), typeToken == subtypeToken, subtypeToken.isAssignableFrom(typeToken)); } for (TypeToken typeToken : allTokens) { assertEquals(typeToken.toString(), typeToken == supertypeToken, supertypeToken.isAssignableFrom(typeToken)); } } public void testIsAssignableFrom_typeVariable() { assertAssignable(TypeToken.of(new TypeCapture() {}.capture()), TypeToken.of(new TypeCapture() {}.capture())); assertNotAssignable(new TypeToken>() {}, new TypeToken>() {}); assertNotAssignable(new TypeToken() {}, TypeToken.of(new TypeCapture() {}.capture())); assertAssignable(TypeToken.of(new TypeCapture() {}.capture()), TypeToken.of(new TypeCapture() {}.capture())); assertNotAssignable(TypeToken.of(new TypeCapture() {}.capture()), TypeToken.of(new TypeCapture() {}.capture())); } public void testIsAssignableFrom_equalWildcardTypes() { assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); } public void testIsAssignableFrom_wildcard_noBound() { assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); } public void testIsAssignableFrom_wildcardType_upperBoundMatch() { // ? extends T assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertNotAssignable(new TypeToken>() {}, new TypeToken>() {}); assertNotAssignable(new TypeToken>() {}, new TypeToken>() {}); // ? extends Number assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); } public void testIsAssignableFrom_wildcardType_lowerBoundMatch() { // ? super T assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertNotAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); // ? super Number assertNotAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); } public , R extends List> void testIsAssignableFrom_recursiveTypeVariableBounds() { assertAssignable(TypeToken.of(new TypeCapture() {}.capture()), TypeToken.of(new TypeCapture() {}.capture())); assertNotAssignable(TypeToken.of(new TypeCapture() {}.capture()), TypeToken.of(new TypeCapture() {}.capture())); assertAssignable(TypeToken.of(new TypeCapture() {}.capture()), new TypeToken>() {}); } public void testIsAssignableFrom_resolved() { assertFalse(Assignability.of().isAssignable()); assertTrue(new Assignability() {}.isAssignable()); assertTrue(new Assignability() {}.isAssignable()); assertFalse(new Assignability() {}.isAssignable()); TypeTokenTest.assignabilityTestWithTypeVariables(); } private static void assignabilityTestWithTypeVariables() { assertTrue(new Assignability() {}.isAssignable()); assertTrue(new Assignability() {}.isAssignable()); assertFalse(new Assignability() {}.isAssignable()); } public void testIsArray_arrayClasses() { assertTrue(TypeToken.of(Object[].class).isArray()); assertTrue(TypeToken.of(Object[][].class).isArray()); assertTrue(TypeToken.of(char[].class).isArray()); assertTrue(TypeToken.of(char[][].class).isArray()); assertTrue(TypeToken.of(byte[].class).isArray()); assertTrue(TypeToken.of(short[].class).isArray()); assertTrue(TypeToken.of(int[].class).isArray()); assertTrue(TypeToken.of(long[].class).isArray()); assertTrue(TypeToken.of(float[].class).isArray()); assertTrue(TypeToken.of(double[].class).isArray()); assertFalse(TypeToken.of(Object.class).isArray()); assertFalse(TypeToken.of(void.class).isArray()); } public void testIsArray_genericArrayClasses() { assertFalse(TypeToken.of(new TypeCapture() {}.capture()).isArray()); assertTrue(new TypeToken() {}.isArray()); assertTrue(new TypeToken() {}.isArray()); } public void testIsArray_wildcardType() throws Exception { assertTrue(TypeToken.of(Types.subtypeOf(Object[].class)).isArray()); assertTrue(TypeToken.of(Types.subtypeOf(int[].class)).isArray()); assertFalse(TypeToken.of(Types.subtypeOf(Object.class)).isArray()); assertFalse(TypeToken.of(Types.supertypeOf(Object[].class)).isArray()); } public void testPrimitiveWrappingAndUnwrapping() { for (Class type : Primitives.allPrimitiveTypes()) { assertIsPrimitive(TypeToken.of(type)); } for (Class type : Primitives.allWrapperTypes()) { assertIsWrapper(TypeToken.of(type)); } assertNotPrimitiveNorWrapper(TypeToken.of(String.class)); assertNotPrimitiveNorWrapper(TypeToken.of(Object[].class)); assertNotPrimitiveNorWrapper(TypeToken.of(Types.subtypeOf(Object.class))); assertNotPrimitiveNorWrapper(new TypeToken>() {}); assertNotPrimitiveNorWrapper(TypeToken.of(new TypeCapture() {}.capture())); } public void testGetComponentType_arrayClasses() { assertEquals(Object.class, TypeToken.of(Object[].class).getComponentType().getType()); assertEquals(Object[].class, TypeToken.of(Object[][].class).getComponentType().getType()); assertEquals(char.class, TypeToken.of(char[].class).getComponentType().getType()); assertEquals(char[].class, TypeToken.of(char[][].class).getComponentType().getType()); assertEquals(byte.class, TypeToken.of(byte[].class).getComponentType().getType()); assertEquals(short.class, TypeToken.of(short[].class).getComponentType().getType()); assertEquals(int.class, TypeToken.of(int[].class).getComponentType().getType()); assertEquals(long.class, TypeToken.of(long[].class).getComponentType().getType()); assertEquals(float.class, TypeToken.of(float[].class).getComponentType().getType()); assertEquals(double.class, TypeToken.of(double[].class).getComponentType().getType()); assertNull(TypeToken.of(Object.class).getComponentType()); assertNull(TypeToken.of(void.class).getComponentType()); } public void testGetComponentType_genericArrayClasses() { assertNull(TypeToken.of(new TypeCapture() {}.capture()).getComponentType()); assertEquals(TypeToken.of(new TypeCapture() {}.capture()), new TypeToken() {}.getComponentType()); assertEquals(new TypeToken() {}, new TypeToken() {}.getComponentType()); } public void testGetComponentType_wildcardType() throws Exception { assertEquals(Types.subtypeOf(Object.class), TypeToken.of(Types.subtypeOf(Object[].class)).getComponentType().getType()); assertEquals(Types.subtypeOf(Object[].class), Types.newArrayType( TypeToken.of(Types.subtypeOf(Object[].class)).getComponentType().getType())); assertEquals(int.class, TypeToken.of(Types.subtypeOf(int[].class)).getComponentType().getType()); assertNull(TypeToken.of(Types.subtypeOf(Object.class)).getComponentType()); assertNull(TypeToken.of(Types.supertypeOf(Object[].class)).getComponentType()); } private interface NumberList {} public void testImplicitUpperBoundForWildcards() { assertAssignable( new TypeToken>() {}, new TypeToken>() {}); assertAssignable( new TypeToken>() {}, new TypeToken>() {}); } public void testMultiBound() { assertAssignable(new TypeToken>() {}, new TypeToken>() {}); assertAssignable(new TypeToken>() {}, new TypeToken>() {}); } public void testToGenericType() { assertEquals(TypeToken.of(String.class), TypeToken.toGenericType(String.class)); assertEquals(new TypeToken() {}, TypeToken.toGenericType(int[].class)); @SuppressWarnings("rawtypes") // Iterable.class TypeToken genericType = TypeToken.toGenericType(Iterable.class); assertEquals(Iterable.class, genericType.getRawType()); assertEquals(Types.newParameterizedType(Iterable.class, Iterable.class.getTypeParameters()[0]), genericType.getType()); } private interface ListIterable extends Iterable> {} private interface StringListIterable extends ListIterable {} private interface ListArrayIterable extends Iterable[]> {} private interface StringListArrayIterable extends ListIterable {} public void testGetSupertype_withTypeVariable() { ParameterizedType expectedType = Types.newParameterizedType(Iterable.class, Types.newParameterizedType(List.class, ListIterable.class.getTypeParameters()[0])); assertEquals(expectedType, TypeToken.of(ListIterable.class).getSupertype(Iterable.class).getType()); } public void testGetSupertype_withoutTypeVariable() { ParameterizedType expectedType = Types.newParameterizedType(Iterable.class, Types.newParameterizedType(List.class, String.class)); assertEquals(expectedType, TypeToken.of(StringListIterable.class).getSupertype(Iterable.class).getType()); } public void testGetSupertype_chained() { @SuppressWarnings("unchecked") // StringListIterable extensd ListIterable TypeToken> listIterableType = (TypeToken>) TypeToken.of(StringListIterable.class).getSupertype(ListIterable.class); ParameterizedType expectedType = Types.newParameterizedType(Iterable.class, Types.newParameterizedType(List.class, String.class)); assertEquals(expectedType, listIterableType.getSupertype(Iterable.class).getType()); } public void testGetSupertype_withArray() { assertEquals(new TypeToken>[]>() {}, TypeToken.of(StringListIterable[].class).getSupertype(Iterable[].class)); assertEquals(int[].class, TypeToken.of(int[].class).getSupertype(int[].class).getType()); assertEquals(Object.class, TypeToken.of(int[].class).getSupertype(Object.class).getType()); assertEquals(int[][].class, TypeToken.of(int[][].class).getSupertype(int[][].class).getType()); assertEquals(Object[].class, TypeToken.of(String[].class).getSupertype(Object[].class).getType()); assertEquals(Object.class, TypeToken.of(String[].class).getSupertype(Object.class).getType()); } public void testGetSupertype_fromWildcard() { @SuppressWarnings("unchecked") // can't do new TypeToken() {} TypeToken> type = (TypeToken>) TypeToken.of(Types.subtypeOf(new TypeToken>() {}.getType())); assertEquals(new TypeToken>() {}, type.getSupertype(Iterable.class)); } public > void testGetSupertype_fromTypeVariable() { @SuppressWarnings("unchecked") // to construct TypeToken from TypeToken.of() TypeToken typeVariableToken = (TypeToken) TypeToken.of(new TypeCapture() {}.capture()); assertEquals(new TypeToken>() {}, typeVariableToken.getSupertype(Iterable.class)); } @SuppressWarnings("rawtypes") // purpose is to test raw type public void testGetSupertype_fromRawClass() { assertEquals(Types.newParameterizedType(Iterable.class, List.class.getTypeParameters()[0]), new TypeToken() {}.getSupertype(Iterable.class).getType()); } @SuppressWarnings({"rawtypes", "unchecked"}) // purpose is to test raw type public void testGetSupertype_notSupertype() { try { new TypeToken>() {}.getSupertype((Class) String.class); fail(); } catch (IllegalArgumentException expected) {} } public void testGetSupertype_fromArray() { assertEquals(new TypeToken[]>() {}, new TypeToken[]>() {}.getSupertype(Iterable[].class)); } private interface ListMap extends Map> {} public void testGetSupertype_fullyGenericType() { ParameterizedType expectedType = Types.newParameterizedType(Map.class, ListMap.class.getTypeParameters()[0], Types.newParameterizedType(List.class, ListMap.class.getTypeParameters()[1])); assertEquals(expectedType, TypeToken.of(ListMap.class).getSupertype(Map.class).getType()); } public void testGetSupertype_fullySpecializedType() { Type expectedType = new TypeToken>>() {}.getType(); assertEquals(expectedType, new TypeToken>() {}.getSupertype(Map.class).getType()); } private interface StringListMap extends ListMap {} public void testGetSupertype_partiallySpecializedType() { Type expectedType = new TypeToken>>() {}.getType(); assertEquals(expectedType, new TypeToken>() {}.getSupertype(Map.class).getType()); } public void testGetSubtype_withTypeVariable() { assertEquals(new TypeToken>() {}, new TypeToken>>() {}.getSubtype(ListIterable.class)); assertEquals(new TypeToken>() {}, new TypeToken[]>>() {}.getSubtype(ListArrayIterable.class)); assertEquals(new TypeToken[]>() {}, new TypeToken[]>[]>() {}.getSubtype(ListArrayIterable[].class)); } public void testGetSubtype_withoutTypeVariable() { assertEquals(StringListIterable.class, TypeToken.of(Iterable.class).getSubtype(StringListIterable.class).getType()); assertEquals(StringListIterable[].class, TypeToken.of(Iterable[].class).getSubtype(StringListIterable[].class).getType()); assertEquals(TypeToken.of(StringListArrayIterable.class), new TypeToken>>() {}.getSubtype(StringListArrayIterable.class)); assertEquals(TypeToken.of(StringListArrayIterable[].class), new TypeToken>[]>() {}.getSubtype(StringListArrayIterable[].class)); } public void testGetSubtype_withArray() { assertEquals(TypeToken.of(StringListIterable[].class), TypeToken.of(Iterable[].class).getSubtype(StringListIterable[].class)); assertEquals(TypeToken.of(String[].class), TypeToken.of(Object[].class).getSubtype(String[].class)); assertEquals(TypeToken.of(int[].class), TypeToken.of(Object.class).getSubtype(int[].class)); } public void testGetSubtype_fromWildcard() { @SuppressWarnings("unchecked") // can't do new TypeToken() {} TypeToken> type = (TypeToken>) TypeToken.of(Types.supertypeOf(new TypeToken>() {}.getType())); assertEquals(new TypeToken>() {}, type.getSubtype(List.class)); } public void testGetSubtype_fromWildcard_lowerBoundNotSupertype() { @SuppressWarnings("unchecked") // can't do new TypeToken() {} TypeToken> type = (TypeToken>) TypeToken.of(Types.supertypeOf(new TypeToken>() {}.getType())); try { type.getSubtype(List.class); fail(); } catch (IllegalArgumentException expected) {} } public void testGetSubtype_fromWildcard_upperBounded() { @SuppressWarnings("unchecked") // can't do new TypeToken() {} TypeToken> type = (TypeToken>) TypeToken.of(Types.subtypeOf(new TypeToken>() {}.getType())); try { type.getSubtype(Iterable.class); fail(); } catch (IllegalArgumentException expected) {} } public > void testGetSubtype_fromTypeVariable() { try { TypeToken.of(new TypeCapture() {}.capture()).getSubtype(List.class); fail(); } catch (IllegalArgumentException expected) {} } @SuppressWarnings("rawtypes") // purpose is to test raw type public void testGetSubtype_fromRawClass() { assertEquals(List.class, new TypeToken() {}.getSubtype(List.class).getType()); } public void testGetSubtype_fromArray() { assertEquals(new TypeToken[]>() {}, new TypeToken[]>() {}.getSubtype(List[].class)); } @SuppressWarnings("unchecked") // To construct TypeToken with TypeToken.of() public void testWhere_circleRejected() { TypeToken> type = new TypeToken>() {}; try { type.where(new TypeParameter() {}, (TypeToken) TypeToken.of(new TypeCapture() {}.capture())); fail(); } catch (IllegalArgumentException expected) {} } public void testWhere() { assertEquals( new TypeToken>() {}, mapOf(String.class, Integer.class)); assertEquals(new TypeToken() {}, arrayOf(int.class)); assertEquals(int[].class, arrayOf(int.class).getRawType()); } @SuppressWarnings("unused") // used by reflection private static class Holder { T element; List list; List[] matrix; void setList(List list) { this.list = list; } } public void testWildcardCaptured_methodParameter_upperBound() throws Exception { TypeToken> type = new TypeToken>() {}; TypeToken parameterType = type.resolveType( Holder.class.getDeclaredMethod("setList", List.class).getGenericParameterTypes()[0]); assertEquals(List.class, parameterType.getRawType()); assertFalse(parameterType.getType().toString(), parameterType.isAssignableFrom(new TypeToken>() {})); } public void testWildcardCaptured_field_upperBound() throws Exception { TypeToken> type = new TypeToken>() {}; TypeToken matrixType = type.resolveType( Holder.class.getDeclaredField("matrix").getGenericType()); assertEquals(List[].class, matrixType.getRawType()); ASSERT.that(matrixType.getType()) .isNotEqualTo(new TypeToken[]>() {}.getType()); } public void testArrayClassPreserved() { assertEquals(int[].class, TypeToken.of(int[].class).getType()); assertEquals(int[][].class, TypeToken.of(int[][].class).getType()); assertEquals(String[].class, TypeToken.of(String[].class).getType()); assertEquals(Integer.class, new TypeToken() {}.getType()); assertEquals(Integer.class, TypeToken.of(Integer.class).getType()); } public void testMethod_getOwnerType() throws NoSuchMethodException { Method sizeMethod = List.class.getMethod("size"); assertEquals(TypeToken.of(List.class), TypeToken.of(List.class).method(sizeMethod).getOwnerType()); assertEquals(new TypeToken>() {}, new TypeToken>() {}.method(sizeMethod).getOwnerType()); } public void testMethod_notDeclaredByType() throws NoSuchMethodException { Method sizeMethod = Map.class.getMethod("size"); try { TypeToken.of(List.class).method(sizeMethod); fail(); } catch (IllegalArgumentException expected) {} } public void testMethod_declaredBySuperclass() throws Exception { Method toStringMethod = Object.class.getMethod("toString"); ImmutableList list = ImmutableList.of("foo"); assertEquals(list.toString(), TypeToken.of(List.class).method(toStringMethod).invoke(list)); } public > void testMethod_returnType_resolvedAgainstTypeBound() throws NoSuchMethodException { Method getMethod = List.class.getMethod("get", int.class); Invokable invokable = new TypeToken(getClass()) {} .method(getMethod) .returning(String.class); assertEquals(TypeToken.of(String.class), invokable.getReturnType()); } public > void testMethod_parameterTypes() throws NoSuchMethodException { Method setMethod = List.class.getMethod("set", int.class, Object.class); Invokable invokable = new TypeToken(getClass()) {}.method(setMethod); ImmutableList params = invokable.getParameters(); assertEquals(2, params.size()); assertEquals(TypeToken.of(int.class), params.get(0).getType()); assertEquals(TypeToken.of(String.class), params.get(1).getType()); } public void testMethod_equals() throws NoSuchMethodException { Method getMethod = List.class.getMethod("get", int.class); Method setMethod = List.class.getMethod("set", int.class, Object.class); new EqualsTester() .addEqualityGroup(Invokable.from(getMethod), Invokable.from(getMethod)) .addEqualityGroup(Invokable.from(setMethod)) .addEqualityGroup(new TypeToken>() {}.method(getMethod)) .addEqualityGroup(new TypeToken>() {}.method(getMethod)) .addEqualityGroup(new TypeToken>() {}.method(setMethod)) .addEqualityGroup(new TypeToken>() {}.method(setMethod)) .testEquals(); } private interface Loser { void lose() throws E; } public > void testMethod_exceptionTypes() throws NoSuchMethodException { Method failMethod = Loser.class.getMethod("lose"); Invokable invokable = new TypeToken(getClass()) {}.method(failMethod); ASSERT.that(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class)); } public void testConstructor_getOwnerType() throws NoSuchMethodException { @SuppressWarnings("rawtypes") // raw class ArrayList.class Constructor constructor = ArrayList.class.getConstructor(); assertEquals(TypeToken.of(ArrayList.class), TypeToken.of(ArrayList.class).constructor(constructor).getOwnerType()); assertEquals(new TypeToken>() {}, new TypeToken>() {}.constructor(constructor).getOwnerType()); } public void testConstructor_notDeclaredByType() throws NoSuchMethodException { Constructor constructor = String.class.getConstructor(); try { TypeToken.of(Object.class).constructor(constructor); fail(); } catch (IllegalArgumentException expected) {} } public void testConstructor_declaredBySuperclass() throws NoSuchMethodException { Constructor constructor = Object.class.getConstructor(); try { TypeToken.of(String.class).constructor(constructor); fail(); } catch (IllegalArgumentException expected) {} } public void testConstructor_equals() throws NoSuchMethodException { Constructor defaultConstructor = ArrayList.class.getConstructor(); Constructor oneArgConstructor = ArrayList.class.getConstructor(int.class); new EqualsTester() .addEqualityGroup(Invokable.from(defaultConstructor), Invokable.from(defaultConstructor)) .addEqualityGroup(Invokable.from(oneArgConstructor)) .addEqualityGroup(new TypeToken>() {}.constructor(defaultConstructor)) .addEqualityGroup(new TypeToken>() {}.constructor(defaultConstructor)) .addEqualityGroup(new TypeToken>() {}.constructor(oneArgConstructor)) .addEqualityGroup(new TypeToken>() {}.constructor(oneArgConstructor)) .testEquals(); } private static class Container { @SuppressWarnings("unused") public Container(T data) {} } public > void testConstructor_parameterTypes() throws NoSuchMethodException { @SuppressWarnings("rawtypes") // Reflection API skew Constructor constructor = Container.class.getConstructor(Object.class); Invokable invokable = new TypeToken(getClass()) {}.constructor(constructor); ImmutableList params = invokable.getParameters(); assertEquals(1, params.size()); assertEquals(TypeToken.of(String.class), params.get(0).getType()); } private static class CannotConstruct { @SuppressWarnings("unused") public CannotConstruct() throws E {} } public > void testConstructor_exceptionTypes() throws NoSuchMethodException { @SuppressWarnings("rawtypes") // Reflection API skew Constructor constructor = CannotConstruct.class.getConstructor(); Invokable invokable = new TypeToken(getClass()) {}.constructor(constructor); ASSERT.that(invokable.getExceptionTypes()).has().item(TypeToken.of(AssertionError.class)); } public void testRejectTypeVariable_class() { assertNoTypeVariable(String.class); assertNoTypeVariable(String[].class); assertNoTypeVariable(int[].class); } public void testRejectTypeVariable_parameterizedType() { assertNoTypeVariable(new TypeCapture>() {}.capture()); } public void testRejectTypeVariable_wildcardType() { assertNoTypeVariable( new TypeCapture>() {}.capture()); assertNoTypeVariable( new TypeCapture>() {}.capture()); } public void testRejectTypeVariable_genericArrayType() { assertNoTypeVariable( new TypeCapture[]>() {}.capture()); } public void testRejectTypeVariable_withTypeVariable() { assertHasTypeVariable(new TypeCapture() {}.capture()); assertHasTypeVariable(new TypeCapture() {}.capture()); assertHasTypeVariable(new TypeCapture>() {}.capture()); assertHasTypeVariable(new TypeCapture>() {}.capture()); assertHasTypeVariable( new TypeCapture>() {}.capture()); assertHasTypeVariable( new TypeCapture>() {}.capture()); } private static class From { class To { Type type() { return new TypeToken>(getClass()) {}.getType(); } } } public void testRejectTypeVariable_withOwnerType() { // Neither has subclass assertHasTypeVariable(new From().new To().type()); assertHasTypeVariable(new From().new To().type()); assertHasTypeVariable(new From().new To().type()); // Owner is subclassed assertHasTypeVariable(new From() {}.new To().type()); assertHasTypeVariable(new From() {}.new To().type()); // Inner is subclassed assertNoTypeVariable(new From().new To() {}.type()); assertHasTypeVariable(new From().new To() {}.type()); assertHasTypeVariable(new From().new To() {}.type()); // both subclassed assertHasTypeVariable(new From() {}.new To() {}.type()); assertNoTypeVariable(new From() {}.new To() {}.type()); assertHasTypeVariable(new From() {}.new To() {}.type()); } private static void assertHasTypeVariable(Type type) { try { TypeToken.of(type).rejectTypeVariables(); fail("Should contain TypeVariable"); } catch (IllegalArgumentException expected) {} } private static void assertNoTypeVariable(Type type) { TypeToken.of(type).rejectTypeVariables(); } private abstract static class RawTypeConsistencyTester & CharSequence> { abstract T returningT(); abstract void acceptT(T t); abstract X returningX(); abstract void acceptX(X x); abstract & CharSequence> T2 returningT2(); abstract > void acceptT2(T2 t2); static void verifyConsitentRawType() { for (Method method : RawTypeConsistencyTester.class.getDeclaredMethods()) { assertEquals(method.getReturnType(), TypeToken.getRawType(method.getGenericReturnType())); for (int i = 0; i < method.getParameterTypes().length; i++) { assertEquals(method.getParameterTypes()[i], TypeToken.getRawType(method.getGenericParameterTypes()[i])); } } } } public void testRawTypes() throws Exception { RawTypeConsistencyTester.verifyConsitentRawType(); assertEquals(Object.class, TypeToken.getRawType(Types.subtypeOf(Object.class))); assertEquals(CharSequence.class, TypeToken.getRawType(Types.subtypeOf(CharSequence.class))); assertEquals(Object.class, TypeToken.getRawType(Types.supertypeOf(CharSequence.class))); } private abstract static class IKnowMyType { TypeToken type() { return new TypeToken(getClass()) {}; } } public void testTypeResolution() { assertEquals(String.class, new IKnowMyType() {}.type().getType()); assertEquals(new TypeToken>() {}, new IKnowMyType>() {}.type()); } public , B extends A> void testSerializable() { reserialize(TypeToken.of(String.class)); reserialize(TypeToken.of(String.class).getTypes()); reserialize(TypeToken.of(String.class).getTypes().classes()); reserialize(TypeToken.of(String.class).getTypes().interfaces()); reserialize(TypeToken.of(String.class).getTypes().rawTypes()); reserialize(TypeToken.of(String.class).getTypes().classes().rawTypes()); reserialize(TypeToken.of(String.class).getTypes().interfaces().rawTypes()); reserialize(new TypeToken() {}); reserialize(new TypeToken>() {}); reserialize(new IKnowMyType>() {}.type()); reserialize(TypeToken.of(new TypeCapture() {}.capture()).getTypes().rawTypes()); try { SerializableTester.reserialize(TypeToken.of(new TypeCapture() {}.capture())); fail(); } catch (RuntimeException expected) {} } public void testSerializable_typeVariableNotSupported() { try { new ITryToSerializeMyTypeVariable().go(); fail(); } catch (RuntimeException expected) {} } private static class ITryToSerializeMyTypeVariable { void go() { SerializableTester.reserialize(TypeToken.of(new TypeCapture() {}.capture())); } } private static T reserialize(T object) { T copy = SerializableTester.reserialize(object); new EqualsTester() .addEqualityGroup(object, copy) .testEquals(); return copy; } public void testTypeResolutionAfterReserialized() { reserialize(new TypeToken() {}); reserialize(new TypeToken>() {}); TypeToken> reserialized = reserialize( new TypeToken>() {}); assertEquals(reserialized, substitute(reserialized, String.class)); } private static TypeToken substitute(TypeToken type, Class arg) { return type.where(new TypeParameter() {}, arg); } private abstract static class ToReproduceGenericSignatureFormatError { private abstract class BaseOuter { abstract class BaseInner {} } private abstract class SubOuter extends BaseOuter { private abstract class SubInner extends BaseInner {} } } // For Guava bug http://code.google.com/p/guava-libraries/issues/detail?id=1025 public void testDespiteGenericSignatureFormatError() { ImmutableSet.copyOf( TypeToken.of(ToReproduceGenericSignatureFormatError.SubOuter.SubInner.class) .getTypes() .rawTypes()); } private abstract static class Entry { TypeToken keyType() { return new TypeToken(getClass()) {}; } TypeToken valueType() { return new TypeToken(getClass()) {}; } } // The A and B type parameters are used inside the test to test type variable public void testEquals() { new EqualsTester() .addEqualityGroup( TypeToken.of(String.class), TypeToken.of(String.class), new Entry() {}.keyType(), new Entry() {}.valueType(), new TypeToken() {}, new TypeToken() {}) .addEqualityGroup( TypeToken.of(Integer.class), new TypeToken() {}, new Entry() {}.keyType(), new Entry() {}.valueType()) .addEqualityGroup( new TypeToken>() {}, new TypeToken>() {}) .addEqualityGroup( new TypeToken>() {}, new TypeToken>() {}) .addEqualityGroup( new TypeToken>() {}, new TypeToken>() {}) .addEqualityGroup( new TypeToken>() {}) .addEqualityGroup( TypeToken.of(new TypeCapture() {}.capture()), TypeToken.of(new TypeCapture() {}.capture())) .addEqualityGroup(TypeToken.of(new TypeCapture() {}.capture())) .testEquals(); } // T is used inside to test type variable public void testToString() { assertEquals(String.class.getName(), new TypeToken() {}.toString()); assertEquals("T", TypeToken.of(new TypeCapture() {}.capture()).toString()); assertEquals("java.lang.String", new Entry() {}.keyType().toString()); } private static TypeToken> mapOf(Class keyType, Class valueType) { return new TypeToken>() {} .where(new TypeParameter() {}, keyType) .where(new TypeParameter() {}, valueType); } private static TypeToken arrayOf(Class componentType) { return new TypeToken() {} .where(new TypeParameter() {}, componentType); } public void testNulls() { new NullPointerTester() .testAllPublicStaticMethods(TypeToken.class); new NullPointerTester() .setDefault(TypeParameter.class, new TypeParameter() {}) .testAllPublicInstanceMethods(TypeToken.of(String.class)); } private static class Assignability { boolean isAssignable() { return new TypeToken(getClass()) {}.isAssignableFrom(new TypeToken(getClass()) {}); } static Assignability of() { return new Assignability(); } } private static void assertAssignable(TypeToken from, TypeToken to) { assertTrue( from.getType() + " is expected to be assignable to " + to.getType(), to.isAssignableFrom(from)); } private static void assertNotAssignable(TypeToken from, TypeToken to) { assertFalse( from.getType() + " shouldn't be assignable to " + to.getType(), to.isAssignableFrom(from)); } private static void assertHasArrayInterfaces(TypeToken arrayType) { assertEquals(arrayInterfaces(), ImmutableSet.copyOf(arrayType.getGenericInterfaces())); } private static ImmutableSet> arrayInterfaces() { ImmutableSet.Builder> builder = ImmutableSet.builder(); for (Class interfaceType : Object[].class.getInterfaces()) { builder.add(TypeToken.of(interfaceType)); } return builder.build(); } private static void assertIsPrimitive(TypeToken type) { assertTrue(type.isPrimitive()); assertNotWrapper(type); assertEquals(TypeToken.of(Primitives.wrap((Class) type.getType())), type.wrap()); } private static void assertNotPrimitive(TypeToken type) { assertFalse(type.isPrimitive()); assertSame(type, type.wrap()); } private static void assertIsWrapper(TypeToken type) { assertNotPrimitive(type); assertEquals(TypeToken.of(Primitives.unwrap((Class) type.getType())), type.unwrap()); } private static void assertNotWrapper(TypeToken type) { assertSame(type, type.unwrap()); } private static void assertNotPrimitiveNorWrapper(TypeToken type) { assertNotPrimitive(type); assertNotWrapper(type); } private interface BaseInterface {} private static class Base implements BaseInterface {} private static class Sub extends Base {} private static CollectionSubject assertThat(Collection actual) { return ASSERT.that(Collections.unmodifiableCollection(actual)); } }