Skip to content

Commit

Permalink
https://github.com/jhalterman/typetools/issues/19
Browse files Browse the repository at this point in the history
  • Loading branch information
mickare committed Feb 11, 2016
1 parent f738619 commit e07d15f
Showing 1 changed file with 61 additions and 39 deletions.
100 changes: 61 additions & 39 deletions src/test/java/net/jodah/typetools/functional/LambdaTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.testng.Assert.assertEquals;

import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
Expand Down Expand Up @@ -88,7 +89,8 @@ interface I1<F, T> {
}

/**
* Asserts that arguments can be resolved from lambda expressions for simple functional interfaces.
* Asserts that arguments can be resolved from lambda expressions for simple functional
* interfaces.
*/
public void shouldResolveArguments() {
Predicate<String> predicate = str -> true;
Expand All @@ -97,25 +99,29 @@ public void shouldResolveArguments() {
Consumer<String> consumer = s -> {
};

assertEquals(TypeResolver.resolveRawArgument(Predicate.class, predicate.getClass()), String.class);
assertEquals(TypeResolver.resolveRawArgument(Predicate.class, predicate.getClass()),
String.class);
assertEquals(TypeResolver.resolveRawArguments(Function.class, fn.getClass()),
new Class<?>[] { String.class, Integer.class });
assertEquals(TypeResolver.resolveRawArgument(Supplier.class, supplier.getClass()), String.class);
assertEquals(TypeResolver.resolveRawArgument(Consumer.class, consumer.getClass()), String.class);
new Class<?>[] {String.class, Integer.class});
assertEquals(TypeResolver.resolveRawArgument(Supplier.class, supplier.getClass()),
String.class);
assertEquals(TypeResolver.resolveRawArgument(Consumer.class, consumer.getClass()),
String.class);
}

public void shouldResolveArgumentsCorrectly() {

final AtomicLong a = new AtomicLong(0);
Function<String, Long> func = (s) -> {
a.incrementAndGet();
return (long)s.hashCode();
return (long) s.hashCode();
};

assertEquals(new Class<?>[] {String.class, Long.class}, TypeResolver.resolveRawArguments(Function.class, func.getClass()));
assertEquals(new Class<?>[] {String.class, Long.class},
TypeResolver.resolveRawArguments(Function.class, func.getClass()));

}

/**
* Asserts that arguments can be resolved from method references for simple functional interfaces.
*/
Expand All @@ -129,36 +135,37 @@ public void shouldResolveArgumentsFromMethodRefs() {
assertEquals(TypeResolver.resolveRawArgument(Predicate.class, p1.getClass()), String.class);
assertEquals(TypeResolver.resolveRawArgument(Predicate.class, p2.getClass()), String.class);
assertEquals(TypeResolver.resolveRawArguments(BiPredicate.class, p3.getClass()),
new Class<?>[] { Baz.class, String.class });
new Class<?>[] {Baz.class, String.class});
assertEquals(TypeResolver.resolveRawArgument(Comparator.class, c.getClass()), String.class);
}

/**
* Asserts that arguments can be resolved for interfaces that contain additional Object.class overriding methods.
* Asserts that arguments can be resolved for interfaces that contain additional Object.class
* overriding methods.
*/
public void shouldResolveArgumentsFromNonSamMethodRef() throws Throwable {
I1<String, Integer> fn = String::compareToIgnoreCase;
assertEquals(TypeResolver.resolveRawArguments(I1.class, fn.getClass()),
new Class<?>[] { String.class, Integer.class });
new Class<?>[] {String.class, Integer.class});
}

/**
* Asserts that method references with primitive type arguments that are auto boxed to primitive wrappers are properly
* handled.
* Asserts that method references with primitive type arguments that are auto boxed to primitive
* wrappers are properly handled.
*
* Note: disabled since method signature exposed via constant pool contains convert(String, Object). Subsequent
* bytecode contains convert(String, String). May need ASM to read.
* Note: disabled since method signature exposed via constant pool contains convert(String,
* Object). Subsequent bytecode contains convert(String, String). May need ASM to read.
*/
@Test(enabled = false)
public void shouldResolveArgumentsForAutoBoxedMethodRefArgument() throws Throwable {
I1<String, Integer> fn = Baz::convert;
assertEquals(TypeResolver.resolveRawArguments(I1.class, fn.getClass()),
new Class<?>[] { String.class, Integer.class });
new Class<?>[] {String.class, Integer.class});
}

/**
* Asserts that arguments can be resolved from lambda expressions for simple functional interfaces that contain
* multiple type parameters.
* Asserts that arguments can be resolved from lambda expressions for simple functional interfaces
* that contain multiple type parameters.
*/
public void shouldResolveMultiArguments() {
BiFunction<String, Long, Integer> biFn = (str1, str2) -> Integer.valueOf(str1 + str2);
Expand All @@ -171,20 +178,20 @@ public void shouldResolveMultiArguments() {
};

assertEquals(TypeResolver.resolveRawArguments(BiFunction.class, biFn.getClass()),
new Class<?>[] { String.class, Long.class, Integer.class });
new Class<?>[] {String.class, Long.class, Integer.class});
assertEquals(TypeResolver.resolveRawArguments(BiConsumer.class, consumer1.getClass()),
new Class<?>[] { String.class, String.class });
new Class<?>[] {String.class, String.class});
assertEquals(TypeResolver.resolveRawArguments(BiConsumer.class, consumer2.getClass()),
new Class<?>[] { String.class, Long.class });
new Class<?>[] {String.class, Long.class});
assertEquals(TypeResolver.resolveRawArguments(Foo.class, foo.getClass()),
new Class<?>[] { String.class, Long.class, Integer.class, Double.class });
new Class<?>[] {String.class, Long.class, Integer.class, Double.class});
assertEquals(TypeResolver.resolveRawArguments(Bar.class, bar.getClass()),
new Class<?>[] { String.class, Long.class, Integer.class, Unknown.class });
new Class<?>[] {String.class, Long.class, Integer.class, Unknown.class});
}

/**
* Asserts that arguments can be resolved from method references for simple functional interfaces that contain
* multiple type parameters.
* Asserts that arguments can be resolved from method references for simple functional interfaces
* that contain multiple type parameters.
*/
public void shouldResolveMultiArgumentsForMethodRefs() {
Baz baz = new Baz();
Expand All @@ -193,48 +200,51 @@ public void shouldResolveMultiArgumentsForMethodRefs() {
Function3<Baz, String, Long, Integer> f3 = Baz::apply;

assertEquals(TypeResolver.resolveRawArguments(BiFunction.class, f1.getClass()),
new Class<?>[] { String.class, Long.class, Integer.class });
new Class<?>[] {String.class, Long.class, Integer.class});
assertEquals(TypeResolver.resolveRawArguments(BiFunction.class, f2.getClass()),
new Class<?>[] { String.class, Long.class, Integer.class });
new Class<?>[] {String.class, Long.class, Integer.class});
assertEquals(TypeResolver.resolveRawArguments(Function3.class, f3.getClass()),
new Class<?>[] { Baz.class, String.class, Long.class, Integer.class });
new Class<?>[] {Baz.class, String.class, Long.class, Integer.class});
}

/**
* Asserts that arguments can be resolved from a lambda expression when declared on a subclass of some type.
* Asserts that arguments can be resolved from a lambda expression when declared on a subclass of
* some type.
*/
public void shouldResolveSubclassArguments() {
FnSubclass<String, Integer> fn = str -> Integer.valueOf(str);
assertEquals(TypeResolver.resolveRawArguments(Function.class, fn.getClass()),
new Class<?>[] { String.class, Integer.class });
new Class<?>[] {String.class, Integer.class});
}

/**
* Asserts that arguments can be resolved from a method reference when declared on a subclass of some type.
* Asserts that arguments can be resolved from a method reference when declared on a subclass of
* some type.
*/
public void shouldResolveSubclassArgumentsForMethodRefs() {
FnSubclass<String, Integer> fn = Integer::valueOf;
assertEquals(TypeResolver.resolveRawArguments(Function.class, fn.getClass()),
new Class<?>[] { String.class, Integer.class });
new Class<?>[] {String.class, Integer.class});
}

public void shouldResolveTransposedSubclassArguments() {
SelectingFn<Integer, Long, String> fn = (String str) -> Integer.valueOf(str);
assertEquals(TypeResolver.resolveRawArguments(SelectingFn.class, fn.getClass()),
new Class<?>[] { Integer.class, Unknown.class, String.class });
new Class<?>[] {Integer.class, Unknown.class, String.class});
assertEquals(TypeResolver.resolveRawArguments(ReverseFn.class, fn.getClass()),
new Class<?>[] { Integer.class, String.class });
new Class<?>[] {Integer.class, String.class});
assertEquals(TypeResolver.resolveRawArguments(Function.class, fn.getClass()),
new Class<?>[] { String.class, Integer.class });
new Class<?>[] {String.class, Integer.class});

StrToInt fn1 = (String str) -> Integer.valueOf(str);
assertEquals(TypeResolver.resolveRawArguments(StrToInt.class, fn1.getClass()), new Class<?>[] {});
assertEquals(TypeResolver.resolveRawArguments(StrToInt.class, fn1.getClass()),
new Class<?>[] {});
assertEquals(TypeResolver.resolveRawArguments(SelectingFn.class, fn1.getClass()),
new Class<?>[] { Integer.class, Long.class, String.class });
new Class<?>[] {Integer.class, Long.class, String.class});
assertEquals(TypeResolver.resolveRawArguments(ReverseFn.class, fn1.getClass()),
new Class<?>[] { Integer.class, String.class });
new Class<?>[] {Integer.class, String.class});
assertEquals(TypeResolver.resolveRawArguments(Function.class, fn1.getClass()),
new Class<?>[] { String.class, Integer.class });
new Class<?>[] {String.class, Integer.class});
}

/**
Expand All @@ -256,4 +266,16 @@ private <T, R> void handlePassedFunction(Function<T, R> fn) {
assertEquals(typeArgs[0], UUID.class);
assertEquals(typeArgs[1], String.class);
}


public static Predicate<Method> withModifiers(int modifier) {
return m -> m.getModifiers() == modifier;
}

public void shouldResolveMethod() {
Predicate<Method> a = withModifiers(1);
Class<?> type = TypeResolver.resolveRawArgument(Predicate.class, a.getClass());
assertEquals(Method.class, type);
}

}

0 comments on commit e07d15f

Please sign in to comment.