package restx.common;
import static restx.common.Types.isAssignableFrom;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.assertj.core.api.JUnitSoftAssertions;
import org.junit.Rule;
import org.junit.Test;
import java.util.AbstractList;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Test cases for {@link Types} methods.
*/
public class TypesTest {
@Rule
public JUnitSoftAssertions softly = new JUnitSoftAssertions();
@Test
public void getRawType_should_return_the_class_of_non_parametrized_types() {
softly.assertThat(Types.getRawType(Integer.class)).isEqualTo(Integer.class);
softly.assertThat(Types.getRawType(String.class)).isEqualTo(String.class);
softly.assertThat(Types.getRawType(int.class)).isEqualTo(int.class);
}
@Test
public void getRawType_should_return_the_reified_class_of_parametrized_types() {
softly.assertThat(Types.getRawType(new TypeReference<List<String>>() {}.getType()))
.isEqualTo(List.class);
softly.assertThat(Types.getRawType(new TypeReference<Map<String, Integer>>() {}.getType()))
.isEqualTo(Map.class);
}
@Test
public void getRawType_should_return_the_class_of_array_types() throws NoSuchMethodException {
softly.assertThat(Types.getRawType(new TypeReference<List<String>[]>() {}.getType()))
.isEqualTo(List[].class);
}
@Test
public void isAssignableFrom_should_return_true_if_types_are_equals() {
softly.assertThat(isAssignableFrom(String.class, String.class)).isTrue();
softly.assertThat(isAssignableFrom(int.class, int.class)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<List<String>>() {}.getType(),
new TypeReference<List<String>>() {}.getType())
).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<List<String>[]>() {}.getType(),
new TypeReference<List<String>[]>() {}.getType())
).isTrue();
softly.assertThat(isAssignableFrom(String.class, Number.class)).isFalse();
softly.assertThat(isAssignableFrom(
new TypeReference<List<String>>() {}.getType(),
new TypeReference<Map<String, Integer>>() {}.getType())
).isFalse();
}
@Test
public void isAssignableFrom_should_work_with_raw_types() {
softly.assertThat(isAssignableFrom(CharSequence.class, String.class)).isTrue();
softly.assertThat(isAssignableFrom(Number.class, Integer.class)).isTrue();
softly.assertThat(isAssignableFrom(List.class, ArrayList.class)).isTrue();
softly.assertThat(isAssignableFrom(Map.class, ArrayList.class)).isFalse();
softly.assertThat(isAssignableFrom(Integer.class, Number.class)).isFalse();
}
@Test
public void isAssignableFrom_should_return_true_for_a_reifiable_type_and_any_of_the_same_type_parameterized() {
softly.assertThat(isAssignableFrom(
List.class,
new TypeReference<List<String>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
List.class,
new TypeReference<List<Integer>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
Map.class,
new TypeReference<List<String>>() {}.getType()
)).isFalse();
softly.assertThat(isAssignableFrom(
Map.class,
new TypeReference<Map<String, Integer>>() {}.getType()
)).isTrue();
}
@Test
public void isAssignableFrom_should_return_true_for_a_reifiable_type_and_any_sub_parameterized_type() {
softly.assertThat(isAssignableFrom(
List.class,
new TypeReference<ArrayList<String>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
List.class,
new TypeReference<AbstractList<Integer>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
Map.class,
new TypeReference<ImmutableList<String>>() {}.getType()
)).isFalse();
softly.assertThat(isAssignableFrom(
Map.class,
new TypeReference<ImmutableMap<String, Integer>>() {}.getType()
)).isTrue();
}
@Test
public void isAssignableFrom_should_work_for_parameterized_interfaces_and_a_direct_implementation() {
// List and AbstractList
softly.assertThat(isAssignableFrom(
new TypeReference<List<String>>() {}.getType(),
new TypeReference<AbstractList<String>>() {}.getType()
)).isTrue();
// GenericInterface and UnTypedImpl
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<UnTypedImpl<String>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<UnTypedImpl<Integer>>() {}.getType()
)).isFalse();
// Map and AbstractMap
softly.assertThat(isAssignableFrom(
new TypeReference<Map<String, Number>>() {}.getType(),
new TypeReference<AbstractMap<String, Number>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<Map<String, Number>>() {}.getType(),
new TypeReference<AbstractMap<Double, Number>>() {}.getType()
)).isFalse();
softly.assertThat(isAssignableFrom(
new TypeReference<Map<String, Number>>() {}.getType(),
new TypeReference<AbstractMap<String, Integer>>() {}.getType()
)).isFalse();
}
@Test
public void isAssignableFrom_should_work_for_parameterized_class_and_a_direct_sub_class() {
// AbstractList and ArrayList
softly.assertThat(isAssignableFrom(
new TypeReference<AbstractList<String>>() {}.getType(),
new TypeReference<ArrayList<String>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<AbstractList<String>>() {}.getType(),
new TypeReference<ArrayList<Number>>() {}.getType()
)).isFalse();
// UnTypedImpl and MoreUnTypedImpl
softly.assertThat(isAssignableFrom(
new TypeReference<UnTypedImpl<String>>() {}.getType(),
new TypeReference<MoreUnTypedImpl<String>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<UnTypedImpl<String>>() {}.getType(),
new TypeReference<MoreUnTypedImpl<Integer>>() {}.getType()
)).isFalse();
// AbstractMap and HashMap
softly.assertThat(isAssignableFrom(
new TypeReference<AbstractMap<String, Number>>() {}.getType(),
new TypeReference<HashMap<String, Number>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<AbstractMap<String, Number>>() {}.getType(),
new TypeReference<HashMap<Double, Number>>() {}.getType()
)).isFalse();
softly.assertThat(isAssignableFrom(
new TypeReference<AbstractMap<String, Number>>() {}.getType(),
new TypeReference<HashMap<String, Integer>>() {}.getType()
)).isFalse();
}
@Test
public void isAssignableFrom_should_work_with_not_direct_sub_types() {
// GenericInterface and MoreUnTypedImpl
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<MoreUnTypedImpl<String>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<MoreUnTypedImpl<Integer>>() {}.getType()
)).isFalse();
}
@Test
public void isAssignableFrom_should_work_with_fixed_generic_interface_implementation() {
// GenericInterface and StringTypedImpl
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
StringTypedImpl.class
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<Integer>>() {}.getType(),
StringTypedImpl.class
)).isFalse();
// GenericInterface and MoreStringTypedImpl
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
MoreStringTypedImpl.class
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<Integer>>() {}.getType(),
MoreStringTypedImpl.class
)).isFalse();
softly.assertThat(isAssignableFrom(
StringTypedImpl.class,
MoreStringTypedImpl.class
)).isTrue();
// GenericInterface and GenericStringTypedImpl
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<GenericStringTypedImpl<Integer>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<Integer>>() {}.getType(),
new TypeReference<GenericStringTypedImpl<Integer>>() {}.getType()
)).isFalse();
// GenericInterface, GenericStringTypedImpl and MoreIntegerGenericStringTypedImpl
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<MoreIntegerGenericStringTypedImpl<Integer>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<Integer>>() {}.getType(),
new TypeReference<MoreIntegerGenericStringTypedImpl<Integer>>() {}.getType()
)).isFalse();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericStringTypedImpl<Integer>>() {}.getType(),
new TypeReference<MoreIntegerGenericStringTypedImpl<Integer>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericStringTypedImpl<Integer>>() {}.getType(),
new TypeReference<MoreIntegerGenericStringTypedImpl<Double>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericStringTypedImpl<String>>() {}.getType(),
new TypeReference<MoreIntegerGenericStringTypedImpl<Double>>() {}.getType()
)).isFalse();
}
@Test
public void isAssignableFrom_should_manage_to_match_generic_variable_from_sub_types_to_super_types() {
// SomethingMap and SuperMap
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<Double>>() {}.getType(),
new TypeReference<SomethingMap<Double, Integer>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<SomethingMap<String, Integer>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<SomethingMap<Number, Integer>>() {}.getType()
)).isFalse();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<Double>>() {}.getType(),
new TypeReference<SuperMap<Integer, Double>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<SuperMap<Integer, String>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<String>>() {}.getType(),
new TypeReference<SuperMap<Integer, Number>>() {}.getType()
)).isFalse();
// FixedSomethingMap and FixedSuperMap
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<Double>>() {}.getType(),
new TypeReference<FixedSuperMap<Integer, Long>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<Double>>() {}.getType(),
new TypeReference<FixedSuperMap<Number, Double>>() {}.getType()
)).isTrue();
softly.assertThat(isAssignableFrom(
new TypeReference<GenericInterface<Integer>>() {}.getType(),
new TypeReference<FixedSuperMap<Number, Double>>() {}.getType()
)).isFalse();
}
/*
some classes and interfaces used in isAssignableFrom test cases
*/
@SuppressWarnings("unused")
public static interface GenericInterface<T> {}
public static class UnTypedImpl<T> implements GenericInterface<T> {}
public static class MoreUnTypedImpl<T> extends UnTypedImpl<T> {}
public static class StringTypedImpl implements GenericInterface<String> {}
public static class MoreStringTypedImpl extends StringTypedImpl {}
@SuppressWarnings("unused")
public static class GenericStringTypedImpl<T> implements GenericInterface<String> {}
@SuppressWarnings("unused")
public static class MoreIntegerGenericStringTypedImpl<T> extends GenericStringTypedImpl<Integer> {}
@SuppressWarnings("unused")
public static class SomethingMap<A, B> implements GenericInterface<A> {}
@SuppressWarnings("unused")
public static class SuperMap<A,B> extends SomethingMap<B, String> {}
@SuppressWarnings("unused")
public static class FixedSomethingMap<A, B> implements GenericInterface<Double> {}
@SuppressWarnings("unused")
public static class FixedSuperMap<A,B> extends FixedSomethingMap<B, String> {}
}