/**
* Copyright 2010 Wealthfront Inc. 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.kaching.platform.common.types;
import static java.util.Arrays.asList;
import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import com.google.inject.TypeLiteral;
import com.kaching.platform.converters.Converter;
@SuppressWarnings("unchecked")
public class UnificationTest {
@Test
public void testGetReturnType1() throws Exception {
assertEquals(
new TypeLiteral<Integer>() {}.getType(),
Unification.getActualTypeArgument(IntegerQuery.class, TopLevel.class, 0));
}
@Test
public void testGetReturnType2() throws Exception {
assertEquals(
new TypeLiteral<Double>() {}.getType(),
Unification.getActualTypeArgument(DoubleAbstractQuery.class, TopLevel.class, 0));
}
@Test
public void testGetReturnType3() throws Exception {
assertEquals(
new TypeLiteral<List<Integer>>() {}.getType(),
Unification.getActualTypeArgument(IntegerListQuery.class, TopLevel.class, 0));
}
@Test
public void testGetReturnType4() throws Exception {
assertEquals(
new TypeLiteral<List<Double>>() {}.getType(),
Unification.getActualTypeArgument(DoubleListAbstractQuery.class, TopLevel.class, 0));
}
@Test
public void testGetReturnType5() throws Exception {
assertEquals(
new TypeLiteral<Double>() {}.getType(),
Unification.getActualTypeArgument(DoubleSecuredQuery.class, TopLevel.class, 0));
}
@Test
public void testGetReturnType6() throws Exception {
assertEquals(
new TypeLiteral<String>() {}.getType(),
Unification.getActualTypeArgument(StringQuery.class, TopLevel.class, 0));
}
@Test @Ignore("broke with java 7")
public void testGetReturnType7() throws Exception {
assertEquals(
new TypeLiteral<byte[]>() {}.getType(),
Unification.getActualTypeArgument(ByteArrayQuery.class, TopLevel.class, 0));
}
@Test
public void instanceOfManyTypeParams1() throws Exception {
assertEquals(
new TypeLiteral<Short>() {}.getType(),
Unification.getActualTypeArgument(
InstanceOfManyTypeParams.class, ManyTypeParams.class, 0));
}
@Test
@SuppressWarnings("rawtypes")
public void instanceOfManyTypeParams2() throws Exception {
assertEquals(
new TypeLiteral<Map>() {}.getType(),
Unification.getActualTypeArgument(
InstanceOfManyTypeParams.class, ManyTypeParams.class, 1));
}
/* MUST PORT SCALA RELATED TESTS!
@Test
public void instanceOfManyTypeParams3() throws Exception {
assertEquals(
new TypeLiteral<List>() {}.getType(),
Unification.getActualTypeArgument(
InstanceOfManyTypeParams.class, ManyTypeParams.class, 2));
}
@Test
public void scalaInstanceOfManyTypeParams0() throws Exception {
assertEquals(
new TypeLiteral<URI>() {}.getType(),
Unification.getActualTypeArgument(
ScalaInstanceOfManyTypeParams.class, ManyTypeParams.class, 0));
}
@Test
public void scalaInstanceOfManyTypeParams1() throws Exception {
assertEquals(
new TypeLiteral<String>() {}.getType(),
Unification.getActualTypeArgument(
ScalaInstanceOfManyTypeParams.class, ManyTypeParams.class, 1));
}
@Test
public void scalaInstanceOfManyTypeParams2() throws Exception {
assertEquals(
new TypeLiteral<Byte>() {}.getType(),
Unification.getActualTypeArgument(
ScalaInstanceOfManyTypeParams.class, ManyTypeParams.class, 2));
}
@Test
@Ignore("scalac does not put type parameters in bytecode when extending an abstract class")
public void scalaInstanceOfAbstractManyTypeParams0() throws Exception {
assertEquals(
new TypeLiteral<URI>() {}.getType(),
Unification.getActualTypeArgument(
ScalaInstanceOfAbstractManyTypeParams.class, ManyTypeParams.class, 0));
}
JAVA CODE
static class AbstractManyTypeParams<A, B, C> implements ManyTypeParams<A, B, C> {
}
SCALA CODE
class ScalaInstanceOfManyTypeParams extends ManyTypeParams[URI, String, Byte] {
}
class ScalaInstanceOfAbstractManyTypeParams extends AbstractManyTypeParams[URI, String, Byte] {
}
*/
@Test(expected = IllegalArgumentException.class)
public void isNotParameterized() throws Exception {
Unification.getActualTypeArgument(
Double.class, Double.class, 0);
}
@Test
public void isNotSubtype() throws Exception {
try {
Unification.getActualTypeArgument(
Foo.class, MidLevel1.class, 0);
fail();
} catch (IllegalArgumentException e) {
assertEquals(
"class com.kaching.platform.common.types.UnificationTest$Foo " +
"does not have class com.kaching.platform.common.types.UnificationTest$MidLevel1 " +
"as super class",
e.getMessage());
}
}
@Test
public void classExtendingClass1() throws Exception {
assertEquals(
String.class,
Unification.getActualTypeArgument(
Sub1.class, Sup1.class, 0));
}
static class Sup1<T> {}
static class Sub1 extends Sup1<String> {}
@Test
public void classExtendingClass2() throws Exception {
assertEquals(
String.class,
Unification.getActualTypeArgument(
SubSub2.class, Sup2.class, 0));
}
@Test
public void classExtendingClass2WithNoParametrization() throws Exception {
try {
Unification.getActualTypeArgument(
SubNoParam2.class, Sup2.class, 0);
fail();
} catch (IllegalArgumentException e) {
assertEquals(
"class com.kaching.platform.common.types.UnificationTest$SubNoParam2 " +
"does extend parametrically class com.kaching.platform.common.types.UnificationTest$Sup2",
e.getMessage());
}
}
static class SupSup2 {}
static class Sup2<T> extends SupSup2 {}
static class Sub2 extends Sup2<String> {}
@SuppressWarnings("rawtypes")
static class SubNoParam2 extends Sup2 {}
static class SubSub2 extends Sub2 {}
@Test
public void implementsMultipleInterfaces() throws Exception {
for (int i = 0; i < 3; i++) {
assertEquals(
asList(String.class, Double.class, Integer.class).get(i),
Unification.getActualTypeArgument(
MultipleInterfaces.class, ManyTypeParams.class, i));
}
}
static class MultipleInterfaces
implements TopLevel<Type>, ManyTypeParams<String, Double, Integer> {}
@Test
public void implementsMultipleInterfacesSomeWithNoParametrization() throws Exception {
for (int i = 0; i < 3; i++) {
assertEquals(
asList(String.class, Double.class, Integer.class).get(i),
Unification.getActualTypeArgument(
MultipleInterfacesSomeWithNoParametrization.class, ManyTypeParams.class, i));
}
}
@SuppressWarnings("rawtypes")
static class MultipleInterfacesSomeWithNoParametrization
implements TopLevel, ManyTypeParams<String, Double, Integer> {}
@Test
public void listOfIntConverter() throws Exception {
assertEquals(
new TypeLiteral<List<Integer>>() {}.getType(),
Unification.getActualTypeArgument(
ListOfIntConverter.class, Converter.class, 0));
}
abstract static class CsvValuesListConverter<L> implements Converter<List<L>> {}
static class ListOfIntConverter extends CsvValuesListConverter<Integer> {
@Override public String toString(List<Integer> value) { return null; }
@Override public List<Integer> fromString(String representation) { return null; }
}
@Test
public void bottomOfMidLevel3() throws Exception {
assertEquals(
String.class,
Unification.getActualTypeArgument(BottomOfMidLevel3.class, TopLevel.class, 0));
}
@Test
@Ignore("issue 22")
public void crazyMerge() throws Exception {
assertEquals(
new TypeLiteral<Map<Integer, String>>() {}.getType(),
Unification.getActualTypeArgument(
MergeOfIntegerAndString.class, ManyTypeParams.class, 0));
assertEquals(
new TypeLiteral<Map<String, Integer>>() {}.getType(),
Unification.getActualTypeArgument(
MergeOfIntegerAndString.class, ManyTypeParams.class, 1));
assertEquals(
new TypeLiteral<List<Map<Integer, String>>>() {}.getType(),
Unification.getActualTypeArgument(
MergeOfIntegerAndString.class, ManyTypeParams.class, 2));
}
static class MergeOfIntegerAndString extends Merge<Integer, String> {}
static class Merge<K, V> implements ManyTypeParams<Map<K, V>, Map<V, K>, List<Map<K, V>>> {}
private static class Foo {}
private interface ManyTypeParams<A, B, C> {}
@SuppressWarnings("rawtypes")
private static class InstanceOfManyTypeParams implements ManyTypeParams<Short, Map, List> {}
private interface TopLevel<T> {}
private static class MidLevel1<T> implements TopLevel<T> {}
private static class MidLevel2<T> implements TopLevel<T> {}
private static class MidLevel3<S, T> implements TopLevel<T> {}
private static abstract class StubQuery extends MidLevel1<String> {}
private static class ByteArrayQuery extends MidLevel1<byte[]> {}
private static class DoubleAbstractQuery extends MidLevel1<Double> {}
private static class IntegerQuery implements TopLevel<Integer> {}
private static class IntegerListQuery implements TopLevel<List<Integer>> {}
private static class DoubleListAbstractQuery extends MidLevel1<List<Double>> {}
private static class DoubleSecuredQuery extends MidLevel2<Double> {}
private static class StringQuery extends StubQuery {}
private static class BottomOfMidLevel3 extends MidLevel3<Integer, String> {}
}