/*
* JBoss, Home of Professional Open Source
* Copyright 2014, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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 org.jboss.weld.tests.unit.resolution;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.FutureTask;
import javax.enterprise.util.TypeLiteral;
import org.jboss.weld.resolution.CovariantTypes;
import org.jboss.weld.util.reflection.GenericArrayTypeImpl;
import org.jboss.weld.util.reflection.ParameterizedTypeImpl;
import org.jboss.weld.util.reflection.WildcardTypeImpl;
import org.junit.Test;
/**
* Test for {@link CovariantTypes}.
*
* @author Jozef Hartinger
*
*/
public class CovariantTypesTest {
/*
* Raw type
*/
@Test
public void testRawTypeAssignableFromRawType() {
assertTrue(CovariantTypes.isAssignableFrom(Number.class, Integer.class));
assertTrue(CovariantTypes.isAssignableFrom(Number.class, Number.class));
assertTrue(CovariantTypes.isAssignableFrom(int.class, int.class));
assertTrue(CovariantTypes.isAssignableFrom(Object.class, int.class));
assertFalse(CovariantTypes.isAssignableFrom(Integer.class, Number.class));
}
@Test
public void testRawArrayAssignableFromRawArray() {
final Type numbers = new Number[0].getClass();
final Type integers = new Integer[0].getClass();
final Type ints = new int[0].getClass();
assertTrue(CovariantTypes.isAssignableFrom(Object.class, numbers));
assertTrue(CovariantTypes.isAssignableFrom(Object.class, integers));
assertTrue(CovariantTypes.isAssignableFrom(Object.class, ints));
assertTrue(CovariantTypes.isAssignableFrom(numbers, numbers));
assertTrue(CovariantTypes.isAssignableFrom(numbers, integers));
assertFalse(CovariantTypes.isAssignableFrom(numbers, ints));
assertTrue(CovariantTypes.isAssignableFrom(integers, integers));
assertFalse(CovariantTypes.isAssignableFrom(integers, ints));
assertFalse(CovariantTypes.isAssignableFrom(numbers, Object.class));
assertFalse(CovariantTypes.isAssignableFrom(integers, Object.class));
assertFalse(CovariantTypes.isAssignableFrom(ints, Object.class));
assertFalse(CovariantTypes.isAssignableFrom(integers, numbers));
assertFalse(CovariantTypes.isAssignableFrom(ints, numbers));
assertTrue(CovariantTypes.isAssignableFrom(new Number[0][].getClass(), new Number[0][].getClass()));
assertTrue(CovariantTypes.isAssignableFrom(new Number[0][].getClass(), new Integer[0][].getClass()));
assertFalse(CovariantTypes.isAssignableFrom(new Integer[0][].getClass(), new Number[0][].getClass()));
}
@Test
public void testRawTypeAssignableFromParameterizedType() {
assertTrue(CovariantTypes.isAssignableFrom(Map.class, new ParameterizedTypeImpl(Map.class, String.class, Integer.class)));
assertTrue(CovariantTypes.isAssignableFrom(Map.class, new ParameterizedTypeImpl(Map.class, Object.class, Object.class)));
assertTrue(CovariantTypes.isAssignableFrom(Map.class, new ParameterizedTypeImpl(HashMap.class, Object.class, Object.class)));
assertFalse(CovariantTypes.isAssignableFrom(Map.class, new ParameterizedTypeImpl(List.class, Object.class)));
}
@Test
@SuppressWarnings("all")
public <A, B extends Number, C extends Runnable & CharSequence> void testRawTypeAssignableFromTypeVariable() {
final Type a = new TypeLiteral<A>() {
}.getType();
final Type b = new TypeLiteral<B>() {
}.getType();
final Type c = new TypeLiteral<C>() {
}.getType();
assertTrue(CovariantTypes.isAssignableFrom(Object.class, a));
assertFalse(CovariantTypes.isAssignableFrom(Number.class, a));
assertFalse(CovariantTypes.isAssignableFrom(Runnable.class, a));
assertTrue(CovariantTypes.isAssignableFrom(Object.class, b));
assertTrue(CovariantTypes.isAssignableFrom(Number.class, b));
assertFalse(CovariantTypes.isAssignableFrom(Integer.class, b));
assertFalse(CovariantTypes.isAssignableFrom(Runnable.class, b));
assertTrue(CovariantTypes.isAssignableFrom(Object.class, c));
assertTrue(CovariantTypes.isAssignableFrom(Runnable.class, c));
assertTrue(CovariantTypes.isAssignableFrom(CharSequence.class, c));
assertFalse(CovariantTypes.isAssignableFrom(String.class, c));
assertFalse(CovariantTypes.isAssignableFrom(Integer.class, c));
}
@Test
public void testRawTypeAssignableFromWildcardType() {
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, Integer.class), new ParameterizedTypeImpl(Collection.class, WildcardTypeImpl.defaultInstance())));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, Integer.class), new ParameterizedTypeImpl(Collection.class, WildcardTypeImpl.withUpperBound(Number.class))));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, Integer.class), new ParameterizedTypeImpl(Collection.class, WildcardTypeImpl.withUpperBound(Integer.class))));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, Integer.class), new ParameterizedTypeImpl(Collection.class, WildcardTypeImpl.withLowerBound(Integer.class))));
}
@Test
public void testRawTypeAssignableFromGenericArrayType() {
assertTrue(CovariantTypes.isAssignableFrom(new List[0].getClass(), new GenericArrayTypeImpl(List.class, Object.class)));
assertTrue(CovariantTypes.isAssignableFrom(new List[0].getClass(), new GenericArrayTypeImpl(List.class, Integer.class)));
assertTrue(CovariantTypes.isAssignableFrom(new List[0].getClass(), new GenericArrayTypeImpl(ArrayList.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(new ArrayList[0].getClass(), new GenericArrayTypeImpl(List.class, Integer.class)));
}
/*
* Parameterized types
*/
@Test
public void testParameterizedTypeAssignableFromRawType() {
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Map.class, Object.class, Object.class), Map.class));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Map.class, Runnable.class, Exception.class), Map.class));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Map.class, Object.class, Object.class), HashMap.class));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Map.class, Runnable.class, Exception.class), HashMap.class));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, String.class), Collection.class));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Comparable.class, Integer.class), Double.class));
}
@Test
public void testParameterizedTypeAssignableFromParameterizedType() {
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Map.class, String.class, Integer.class), new ParameterizedTypeImpl(Map.class, String.class, Integer.class)));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Runnable.class), new ParameterizedTypeImpl(List.class, Runnable.class)));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Object.class), new ParameterizedTypeImpl(List.class, Object.class)));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Map.class, String.class, Integer.class), new ParameterizedTypeImpl(HashMap.class, String.class, Integer.class)));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Runnable.class), new ParameterizedTypeImpl(ArrayList.class, Runnable.class)));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Object.class), new ParameterizedTypeImpl(ArrayList.class, Object.class)));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Object.class), new ParameterizedTypeImpl(List.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Object.class), new ParameterizedTypeImpl(List.class, Runnable.class)));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Number.class), new ParameterizedTypeImpl(List.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Number.class), new ParameterizedTypeImpl(List.class, Runnable.class)));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Integer.class), new ParameterizedTypeImpl(List.class, Number.class)));
}
@Test
@SuppressWarnings("all")
public <A extends Collection<Number>, B extends List<Runnable> & Comparable<CharSequence>, C extends B> void testParameterizedTypeAssignableFromTypeVariable() {
final Type a = new TypeLiteral<A>() {
}.getType();
final Type b = new TypeLiteral<B>() {
}.getType();
final Type c = new TypeLiteral<C>() {
}.getType();
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, Number.class), a));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Iterable.class, Number.class), a));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Number.class), a));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Iterable.class, Object.class), a));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Iterable.class, Integer.class), a));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Iterable.class, Runnable.class), b));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, Runnable.class), b));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Runnable.class), b));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Comparable.class, CharSequence.class), b));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(ArrayList.class, Runnable.class), b));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Object.class), b));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, FutureTask.class), b));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Comparable.class, String.class), b));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Comparable.class, Object.class), b));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Iterable.class, Runnable.class), c));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, Runnable.class), c));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Runnable.class), c));
assertTrue(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Comparable.class, CharSequence.class), c));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(ArrayList.class, Runnable.class), c));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Object.class), c));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, FutureTask.class), c));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Comparable.class, String.class), c));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Comparable.class, Object.class), c));
}
@Test
public void testParameterizedTypeAssignableFromWildcardType() {
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, new ParameterizedTypeImpl(Collection.class, Integer.class)), new ParameterizedTypeImpl(Collection.class, WildcardTypeImpl.defaultInstance())));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, new ParameterizedTypeImpl(Collection.class, Integer.class)), new ParameterizedTypeImpl(Collection.class, WildcardTypeImpl.withUpperBound(Iterable.class))));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, new ParameterizedTypeImpl(Collection.class, Integer.class)), new ParameterizedTypeImpl(Collection.class, WildcardTypeImpl.withUpperBound(Collection.class))));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(Collection.class, new ParameterizedTypeImpl(Collection.class, Integer.class)), new ParameterizedTypeImpl(Collection.class, WildcardTypeImpl.withLowerBound(new ParameterizedTypeImpl(Collection.class, Integer.class)))));
}
@Test
public void testParameterizedTypeAssignableFromGenericArrayType() {
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Integer.class), new GenericArrayTypeImpl(List.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(new ParameterizedTypeImpl(List.class, Integer.class), new GenericArrayTypeImpl(ArrayList.class, Integer.class)));
}
/*
* Type variables
*/
@Test
@SuppressWarnings("serial")
public <T, S extends Number> void testTypeVariableAssignableFromRawType() {
Type t = new TypeLiteral<T>() {
}.getType();
Type s = new TypeLiteral<S>() {
}.getType();
assertFalse(CovariantTypes.isAssignableFrom(t, Object.class));
assertFalse(CovariantTypes.isAssignableFrom(t, List.class));
assertFalse(CovariantTypes.isAssignableFrom(s, Object.class));
assertFalse(CovariantTypes.isAssignableFrom(s, Number.class));
assertFalse(CovariantTypes.isAssignableFrom(s, Long.class));
}
@Test
@SuppressWarnings("serial")
public <T, S extends List<Number>> void testTypeVariableAssignableFromParameterizedType() {
Type t = new TypeLiteral<T>() {
}.getType();
Type s = new TypeLiteral<S>() {
}.getType();
assertFalse(CovariantTypes.isAssignableFrom(t, new ParameterizedTypeImpl(List.class, Object.class)));
assertFalse(CovariantTypes.isAssignableFrom(t, new ParameterizedTypeImpl(List.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(s, new ParameterizedTypeImpl(List.class, Object.class)));
assertFalse(CovariantTypes.isAssignableFrom(s, new ParameterizedTypeImpl(List.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(s, new ParameterizedTypeImpl(List.class, Long.class)));
}
@Test
@SuppressWarnings("all")
public <A, B, C extends Number, D extends Integer> void testTypeVariableAssignableFromTypeVariable() {
final int count = 5;
Type[] typeVariables = new Type[count];
typeVariables[0] = new TypeLiteral<A>() {
}.getType();
typeVariables[1] = new TypeLiteral<B>() {
}.getType();
typeVariables[2] = new TypeLiteral<C>() {
}.getType();
typeVariables[3] = new TypeLiteral<D>() {
}.getType();
typeVariables[4] = new TypeLiteral<D[]>() {
}.getType();
// type variables should only be assignable if they are equal (unless one extends the other)
for (int i = 0; i < count; i++) {
for (int j = 0; j < count; j++) {
if (i == j) {
assertTrue(CovariantTypes.isAssignableFrom(typeVariables[i], typeVariables[j]));
} else {
assertFalse(CovariantTypes.isAssignableFrom(typeVariables[i], typeVariables[j]));
}
}
}
}
@Test
@SuppressWarnings("serial")
public <A, B extends A, C extends A, D extends C, E extends D> void testTypeVariableAssignableFromTypeVariable2() {
final int count = 5;
Type[] typeVariables = new Type[count];
typeVariables[0] = new TypeLiteral<A>() {
}.getType();
typeVariables[1] = new TypeLiteral<B>() {
}.getType();
typeVariables[2] = new TypeLiteral<C>() {
}.getType();
typeVariables[3] = new TypeLiteral<D>() {
}.getType();
typeVariables[4] = new TypeLiteral<E>() {
}.getType();
// a type variable should only be assignable from itself and from a type variable extending it (even transitively)
for (int i = 0; i < count; i++) {
for (int j = 0; j < count; j++) {
/*
* E (4) extends D (3) extends C (2) extends A (0)
* B (1) extends A (0)
*/
if (i == j || i == 0 || (i < j && i != 1)) {
assertTrue(CovariantTypes.isAssignableFrom(typeVariables[i], typeVariables[j]));
} else {
assertFalse(CovariantTypes.isAssignableFrom(typeVariables[i], typeVariables[j]));
}
}
}
}
@Test
@SuppressWarnings("all")
public <A, B extends Number> void testTypeVariableAssignableFromWildcard() {
Type a = new TypeLiteral<A>() {
}.getType();
Type b = new TypeLiteral<B>() {
}.getType();
assertFalse(CovariantTypes.isAssignableFrom(a, WildcardTypeImpl.defaultInstance()));
assertFalse(CovariantTypes.isAssignableFrom(a, WildcardTypeImpl.withUpperBound(Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(a, WildcardTypeImpl.withLowerBound(Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, WildcardTypeImpl.defaultInstance()));
assertFalse(CovariantTypes.isAssignableFrom(b, WildcardTypeImpl.withUpperBound(Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, WildcardTypeImpl.withLowerBound(Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, WildcardTypeImpl.withUpperBound(Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, WildcardTypeImpl.withLowerBound(Integer.class)));
}
@Test
@SuppressWarnings("all")
public <A, B extends List<Integer>> void testTypeVariableAssignableFromGenericArrayType() {
Type a = new TypeLiteral<A>() {
}.getType();
Type b = new TypeLiteral<B>() {
}.getType();
assertFalse(CovariantTypes.isAssignableFrom(a, new GenericArrayTypeImpl(List.class, Object.class)));
assertFalse(CovariantTypes.isAssignableFrom(a, new GenericArrayTypeImpl(List.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(a, new GenericArrayTypeImpl(List.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, new GenericArrayTypeImpl(List.class, Object.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, new GenericArrayTypeImpl(List.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, new GenericArrayTypeImpl(List.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, new GenericArrayTypeImpl(ArrayList.class, Object.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, new GenericArrayTypeImpl(ArrayList.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(b, new GenericArrayTypeImpl(ArrayList.class, Integer.class)));
}
/*
* Wildcard
*/
@Test
public void testWildcardAssignableFromRawType() {
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), Number.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Number.class), Number.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Integer.class), Number.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Number.class), Number.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Number.class), Object.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Number.class), Integer.class));
}
@Test
@SuppressWarnings("serial")
public <A, B extends Number, C extends B, D extends Number & Serializable> void testWildcardWithTypeVariableAssignableFromRawType() {
final Type a = new TypeLiteral<A>() {
}.getType();
final Type b = new TypeLiteral<B>() {
}.getType();
final Type c = new TypeLiteral<C>() {
}.getType();
final Type d = new TypeLiteral<D>() {
}.getType();
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(a), Object.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(b), Object.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(b), Number.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(b), Integer.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(c), Object.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(c), Number.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(c), Integer.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(d), Number.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(d), Serializable.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(a), Object.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(a), Number.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(b), Object.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(b), Number.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(b), Integer.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(c), Object.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(c), Number.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(c), Integer.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(d), Object.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(d), Number.class));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(d), Serializable.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(d), Integer.class));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(d), Runnable.class));
}
@Test
public void testWildcardAssignableFromParameterizedType() {
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), new ParameterizedTypeImpl(Collection.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(Collection.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(List.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(ArrayList.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(Collection.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(Collection.class, Object.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(Collection.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(Iterable.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(List.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(ArrayList.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(Collection.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(new ParameterizedTypeImpl(Collection.class, Number.class)), new ParameterizedTypeImpl(Collection.class, Object.class)));
}
@Test
@SuppressWarnings("serial")
public <A, B extends Number, C extends Runnable & Appendable> void testWildcardAssignableFromTypeVariable() {
final Type a = new TypeLiteral<A>() {
}.getType();
final Type b = new TypeLiteral<B>() {
}.getType();
final Type c = new TypeLiteral<C>() {
}.getType();
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), a));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), b));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), c));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Number.class), b));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Integer.class), b));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Number.class), b));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Integer.class), b));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Runnable.class), c));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Appendable.class), c));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Runnable.class), c));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Appendable.class), c));
}
@Test
@SuppressWarnings("serial")
public <A, B extends A, C extends A, D extends C, E extends D> void testWildcardWithTypeVariableAssignableFromTypeVariable() {
final int count = 5;
Type[] typeVariables = new Type[count];
typeVariables[0] = new TypeLiteral<A>() {
}.getType();
typeVariables[1] = new TypeLiteral<B>() {
}.getType();
typeVariables[2] = new TypeLiteral<C>() {
}.getType();
typeVariables[3] = new TypeLiteral<D>() {
}.getType();
typeVariables[4] = new TypeLiteral<E>() {
}.getType();
for (int i = 0; i < count; i++) {
for (int j = 0; j < count; j++) {
/*
* E (4) extends D (3) extends C (2) extends A (0)
* B (1) extends A (0)
*/
if (i == j || i == 0 || (i < j && i != 1)) {
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(typeVariables[i]), typeVariables[j]));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(typeVariables[j]), typeVariables[i]));
} else {
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(typeVariables[i]), typeVariables[j]));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(typeVariables[j]), typeVariables[i]));
}
}
}
}
@Test
public void testWildcardAssignableFromWildcard() {
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), WildcardTypeImpl.defaultInstance()));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), WildcardTypeImpl.withUpperBound(Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Number.class), WildcardTypeImpl.withUpperBound(Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Number.class), WildcardTypeImpl.defaultInstance()));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Integer.class), WildcardTypeImpl.defaultInstance()));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Integer.class), WildcardTypeImpl.withUpperBound(Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Integer.class), WildcardTypeImpl.withUpperBound(Integer.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), WildcardTypeImpl.withLowerBound(Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Number.class), WildcardTypeImpl.withLowerBound(Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Integer.class), WildcardTypeImpl.withLowerBound(Integer.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Number.class), WildcardTypeImpl.withLowerBound(Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Integer.class), WildcardTypeImpl.withLowerBound(Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Number.class), WildcardTypeImpl.withLowerBound(Integer.class)));
}
@Test
@SuppressWarnings("serial")
public <A extends Throwable, B extends A, C extends B, D extends Exception> void testWildcardAssignableFromWildcard2() {
// (both) wildcards bounded by a type variable
final int count = 4;
Type[] typeVariables = new Type[count];
final Type a = typeVariables[0] = new TypeLiteral<A>() {
}.getType();
final Type b = typeVariables[1] = new TypeLiteral<B>() {
}.getType();
final Type c = typeVariables[2] = new TypeLiteral<C>() {
}.getType();
final Type d = typeVariables[3] = new TypeLiteral<D>() {
}.getType();
for (int i = 0; i < count; i++) {
// unbounded wildcard should be assignable from anything
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), WildcardTypeImpl.withUpperBound(typeVariables[i])));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), WildcardTypeImpl.withLowerBound(typeVariables[i])));
for (int j = 0; j < count; j++) {
// wildcard with an upper bound is UNassignable from a wildcard with a lower bound and vice versa
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(typeVariables[i]), WildcardTypeImpl.withLowerBound(typeVariables[j])));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(typeVariables[i]), WildcardTypeImpl.withUpperBound(typeVariables[j])));
if (i == j || (i < j && j != 3)) {
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(typeVariables[i]), WildcardTypeImpl.withUpperBound(typeVariables[j])));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(typeVariables[j]), WildcardTypeImpl.withLowerBound(typeVariables[i])));
} else {
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(typeVariables[i]), WildcardTypeImpl.withUpperBound(typeVariables[j])));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(typeVariables[j]), WildcardTypeImpl.withLowerBound(typeVariables[i])));
}
}
}
// one wildcard bounded by a class and the other bounded by a type variable
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Exception.class), WildcardTypeImpl.withUpperBound(d)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(RuntimeException.class), WildcardTypeImpl.withUpperBound(d)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Serializable.class), WildcardTypeImpl.withUpperBound(b)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Throwable.class), WildcardTypeImpl.withUpperBound(b)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Exception.class), WildcardTypeImpl.withUpperBound(b)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(a), WildcardTypeImpl.withLowerBound(Throwable.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(c), WildcardTypeImpl.withLowerBound(Throwable.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(a), WildcardTypeImpl.withLowerBound(Exception.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(c), WildcardTypeImpl.withLowerBound(Exception.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(d), WildcardTypeImpl.withLowerBound(Throwable.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(d), WildcardTypeImpl.withLowerBound(Exception.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(d), WildcardTypeImpl.withLowerBound(RuntimeException.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(RuntimeException.class), WildcardTypeImpl.withLowerBound(a)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Throwable.class), WildcardTypeImpl.withLowerBound(a)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(RuntimeException.class), WildcardTypeImpl.withLowerBound(d)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Throwable.class), WildcardTypeImpl.withLowerBound(d)));
// mix upper bounds with lower bounds
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(Exception.class), WildcardTypeImpl.withLowerBound(d)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(Exception.class), WildcardTypeImpl.withUpperBound(d)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(d), WildcardTypeImpl.withUpperBound(Exception.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(d), WildcardTypeImpl.withLowerBound(Exception.class)));
}
@Test
public void testWildcardAssignableFromGenericArrayType() {
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.defaultInstance(), new GenericArrayTypeImpl(List.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(new GenericArrayTypeImpl(List.class, Number.class)), new GenericArrayTypeImpl(List.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(new GenericArrayTypeImpl(List.class, Number.class)), new GenericArrayTypeImpl(ArrayList.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withUpperBound(new GenericArrayTypeImpl(List.class, Number.class)), new GenericArrayTypeImpl(Collection.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(new GenericArrayTypeImpl(List.class, Number.class)), new GenericArrayTypeImpl(List.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(new GenericArrayTypeImpl(List.class, Number.class)), new GenericArrayTypeImpl(Collection.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(WildcardTypeImpl.withLowerBound(new GenericArrayTypeImpl(List.class, Number.class)), new GenericArrayTypeImpl(ArrayList.class, Number.class)));
}
/*
* GenericArrayType
*/
@Test
public void testGenericArrayTypeAssignableFromRawType() {
assertTrue(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(List.class, Number.class), new List[0].getClass()));
assertTrue(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(List.class, Number.class), new ArrayList[0].getClass()));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(List.class, Number.class), new Object[0].getClass()));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(List.class, Number.class), new Set[0].getClass()));
}
@Test
public void testGenericArrayTypeAssignableFromParameterizedType() {
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(List.class, Number.class), new ParameterizedTypeImpl(List.class, Object.class)));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(List.class, Number.class), new ParameterizedTypeImpl(List.class, Number.class)));
}
@Test
@SuppressWarnings("serial")
public <A, B extends List<Number>> void testGenericArrayTypeAssignableFromTypeVariable() {
Type a = new TypeLiteral<A>() {
}.getType();
Type b = new TypeLiteral<B>() {
}.getType();
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(List.class, Number.class), a));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(List.class, Number.class), b));
}
@Test
@SuppressWarnings("all")
public <A, B extends Number> void testGenericArrayTypeAssignableFromWildcard() {
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), WildcardTypeImpl.defaultInstance()));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), WildcardTypeImpl.withUpperBound(new ParameterizedTypeImpl(Collection.class, Number.class))));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), WildcardTypeImpl.withLowerBound(new ParameterizedTypeImpl(Collection.class, Number.class))));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), WildcardTypeImpl.withUpperBound(new ParameterizedTypeImpl(Collection.class, Integer.class))));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), WildcardTypeImpl.withLowerBound(new ParameterizedTypeImpl(Collection.class, Integer.class))));
}
@Test
public void testGenericArrayTypeAssignableFromGenericArrayType() {
assertTrue(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), new GenericArrayTypeImpl(Collection.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), new GenericArrayTypeImpl(List.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), new GenericArrayTypeImpl(ArrayList.class, Number.class)));
assertTrue(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, WildcardTypeImpl.defaultInstance()), new GenericArrayTypeImpl(ArrayList.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), new GenericArrayTypeImpl(Iterable.class, Number.class)));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), new GenericArrayTypeImpl(Collection.class, Object.class)));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), new GenericArrayTypeImpl(Collection.class, Integer.class)));
assertFalse(CovariantTypes.isAssignableFrom(new GenericArrayTypeImpl(Collection.class, Number.class), new GenericArrayTypeImpl(Collection.class, Double.class)));
}
}