Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

jitting arguments

  • Loading branch information...
commit 379f282fd480c2b22b91f686d598fb29583320a7 1 parent 49abdf4
@mariofusco authored
View
2  LambdajDemoTest.bat
@@ -1,3 +1,3 @@
set MAVEN_REPO=C:\Users\Mario\.m2\repository
-java -server -Xms512M -Xmx512M -cp %MAVEN_REPO%/cglib/cglib-nodep/2.2/cglib-nodep-2.2.jar;%MAVEN_REPO%/org/hamcrest/hamcrest-all/1.1/hamcrest-all-1.1.jar;%MAVEN_REPO%/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar;%MAVEN_REPO%/org/objenesis/objenesis/1.2/objenesis-1.2.jar;target/classes;target/test-classes ch.lambdaj.demo.LambdaDemoTestMain %1
+java -server -Xms512M -Xmx512M -cp %MAVEN_REPO%/cglib/cglib-nodep/2.2.2/cglib-nodep-2.2.2.jar;%MAVEN_REPO%/org/hamcrest/hamcrest-all/1.1/hamcrest-all-1.1.jar;%MAVEN_REPO%/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar;%MAVEN_REPO%/org/objenesis/objenesis/1.2/objenesis-1.2.jar;target/classes;target/test-classes ch.lambdaj.demo.LambdaDemoTestMain %1
View
4 src/main/java/ch/lambdaj/Lambda.java
@@ -35,7 +35,9 @@
public final class Lambda {
private Lambda() { }
-
+
+ public static int jitThreshold = 0;
+
/**
* Constructs a proxy object that mocks the given Class registering all the subsequent invocations on the object.
* @param clazz The class of the object to be mocked
View
29 src/main/java/ch/lambdaj/function/argument/Argument.java
@@ -4,6 +4,12 @@
package ch.lambdaj.function.argument;
+import ch.lambdaj.Lambda;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
/**
* An Argument represents a statically defined sequence of method invocations on a given Class.
* @author Mario Fusco
@@ -11,9 +17,19 @@
public class Argument<T> {
private final InvocationSequence invocationSequence;
-
- Argument(InvocationSequence invocationSequence) {
+
+ private final boolean isJittable;
+
+ private Invoker jittedInvoker;
+
+ private AtomicInteger invocationCounter = new AtomicInteger(0);
+
+ private static final Map<String, Invoker> invokerCache = new HashMap<String, Invoker>();
+
+ Argument(InvocationSequence invocationSequence) {
this.invocationSequence = invocationSequence;
+ isJittable = Lambda.jitThreshold >= 0 && invocationSequence.isJittable();
+ if (isJittable) jittedInvoker = invokerCache.get(invocationSequence.toString());
}
/**
@@ -32,6 +48,15 @@ public String getInkvokedPropertyName() {
*/
@SuppressWarnings("unchecked")
public T evaluate(Object object) {
+ if (jittedInvoker != null) return (T)jittedInvoker.invokeOn(object);
+ if (!isJittable) return (T)invocationSequence.invokeOn(object);
+
+ if (invocationCounter.getAndIncrement() == Lambda.jitThreshold) {
+ jittedInvoker = new InvokerJitter(object, invocationSequence).jitInvoker();
+ invokerCache.put(invocationSequence.toString(), jittedInvoker);
+ return (T)jittedInvoker.invokeOn(object);
+ }
+
return (T)invocationSequence.invokeOn(object);
}
View
17 src/main/java/ch/lambdaj/function/argument/Invocation.java
@@ -37,6 +37,10 @@
}
}
+ boolean hasArguments() {
+ return weakArgs != null;
+ }
+
private Object[] getConcreteArgs() {
if (weakArgs == null) return new Object[0];
Object[] args = new Object[weakArgs.length];
@@ -77,14 +81,13 @@ Object invokeOn(Object object) {
*/
@Override
public String toString() {
+ if (weakArgs == null) return invokedMethod.toString();
StringBuilder sb = new StringBuilder(invokedMethod.toString());
- if (weakArgs != null) {
- sb.append(" with args ");
- boolean first = true;
- for (ParameterReference arg : weakArgs) {
- sb.append(first ? "" : ", ").append(arg.get());
- first = false;
- }
+ sb.append(" with args ");
+ boolean first = true;
+ for (ParameterReference arg : weakArgs) {
+ sb.append(first ? "" : ", ").append(arg.get());
+ first = false;
}
return sb.toString();
}
View
17 src/main/java/ch/lambdaj/function/argument/InvocationSequence.java
@@ -10,12 +10,12 @@
* @author Mario Fusco
* @author Frode Carlsen
*/
-final class InvocationSequence {
+final class InvocationSequence implements Invoker {
private static final long serialVersionUID = 1L;
private final Class<?> rootInvokedClass;
private String inkvokedPropertyName;
- private Invocation lastInvocation;
+ Invocation lastInvocation;
private transient int hashCode;
InvocationSequence(Class<?> rootInvokedClass) {
@@ -80,9 +80,8 @@ public int hashCode() {
return hashCode;
}
- @SuppressWarnings("unchecked")
- public <T> T invokeOn(Object object) {
- return (T)invokeOn(lastInvocation, object);
+ public Object invokeOn(Object object) {
+ return invokeOn(lastInvocation, object);
}
private Object invokeOn(Invocation invocation, Object value) {
@@ -91,6 +90,14 @@ private Object invokeOn(Invocation invocation, Object value) {
return invocation.invokeOn(value);
}
+ boolean isJittable() {
+ return lastInvocation != null && isJittable(lastInvocation);
+ }
+
+ private boolean isJittable(Invocation invocation) {
+ return !invocation.hasArguments() && (invocation.previousInvocation == null || isJittable(invocation.previousInvocation));
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder(100);
View
5 src/main/java/ch/lambdaj/function/argument/Invoker.java
@@ -0,0 +1,5 @@
+package ch.lambdaj.function.argument;
+
+public interface Invoker {
+ Object invokeOn(Object object);
+}
View
130 src/main/java/ch/lambdaj/function/argument/InvokerJitter.java
@@ -0,0 +1,130 @@
+package ch.lambdaj.function.argument;
+
+import net.sf.cglib.asm.ClassWriter;
+import net.sf.cglib.asm.Label;
+import net.sf.cglib.asm.MethodVisitor;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static net.sf.cglib.asm.Opcodes.*;
+
+public class InvokerJitter {
+
+ private static final AtomicInteger jitCounter = new AtomicInteger(1);
+
+ private final InternalClassLoader classLoader;
+ private final InvocationSequence invocationSequence;
+
+ InvokerJitter(Object invokedObject, InvocationSequence invocationSequence) {
+ this(invokedObject.getClass().getClassLoader(), invocationSequence);
+ }
+
+ InvokerJitter(ClassLoader classLoader, InvocationSequence invocationSequence) {
+ this.classLoader = new InternalClassLoader(classLoader);;
+ this.invocationSequence = invocationSequence;
+ }
+
+ Invoker jitInvoker() {
+ try {
+ int id = jitCounter.getAndIncrement();
+ Class<?> clazz = classLoader.defineClass("ch.lambdaj.function.argument.Invoker_" + id, generateBytecode(id));
+ return (Invoker)clazz.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private byte[] generateBytecode(int id) {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
+ cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "ch/lambdaj/function/argument/Invoker_" + id, null, "java/lang/Object", new String[]{"ch/lambdaj/function/argument/Invoker"});
+ jitEmptyConstructor(cw);
+ jitInvocationMethod(cw);
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ private void jitEmptyConstructor(ClassWriter cw) {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
+ private void jitInvocationMethod(ClassWriter cw) {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "invokeOn", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 1);
+ jitInvocationSequence(mv);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
+ private void jitInvocationSequence(MethodVisitor mv) {
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitTypeInsn(CHECKCAST, getClassName(invocationSequence.getRootInvokedClass()));
+ jitInvocation(mv, invocationSequence.lastInvocation);
+ }
+
+ private void jitInvocation(MethodVisitor mv, Invocation invocation) {
+ if (invocation.previousInvocation != null) jitInvocation(mv, invocation.previousInvocation);
+ mv.visitVarInsn(ASTORE, 2);
+ Label nonNull = new Label();
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitJumpInsn(IFNONNULL, nonNull);
+ mv.visitInsn(ACONST_NULL);
+ mv.visitInsn(ARETURN);
+ mv.visitLabel(nonNull);
+ mv.visitVarInsn(ALOAD, 2);
+ Method method = invocation.getInvokedMethod();
+ if (method.getDeclaringClass().isInterface()) {
+ mv.visitMethodInsn(INVOKEINTERFACE, getClassName(method.getDeclaringClass()), method.getName(), "()" + getInternalName(method.getReturnType()));
+ } else {
+ mv.visitMethodInsn(INVOKEVIRTUAL, getClassName(method.getDeclaringClass()), method.getName(), "()" + getInternalName(method.getReturnType()));
+ }
+ primitiveToObject(mv, method.getReturnType());
+ }
+
+ private String getClassName(Class<?> clazz) {
+ return clazz.getName().replace('.', '/');
+ }
+
+ private String getInternalName(Class<?> clazz) {
+ if (!clazz.isPrimitive()) return "L" + getClassName(clazz) + ";";
+ if (clazz == int.class) return "I";
+ if (clazz == long.class) return "J";
+ if (clazz == double.class) return "D";
+ if (clazz == float.class) return "F";
+ if (clazz == boolean.class) return "Z";
+ if (clazz == char.class) return "C";
+ if (clazz == short.class) return "S";
+ return "B";
+ }
+
+ private void primitiveToObject(MethodVisitor mv, Class<?> clazz) {
+ if (!clazz.isPrimitive()) return;
+ if (clazz == int.class) mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
+ else if (clazz == long.class) mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
+ else if (clazz == double.class) mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
+ else if (clazz == float.class) mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
+ else if (clazz == boolean.class) mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
+ else if (clazz == char.class) mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
+ else if (clazz == short.class) mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
+ else if (clazz == byte.class) mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
+ }
+
+ private static class InternalClassLoader extends ClassLoader {
+
+ InternalClassLoader(ClassLoader classLoader) {
+ super(classLoader);
+ }
+
+ Class<?> defineClass(String name, byte[] b) {
+ return defineClass(name, b, 0, b.length);
+ }
+ }
+}
View
88 src/test/java/ch/lambdaj/demo/LambdaDemoTestMain.java
@@ -81,7 +81,7 @@ private static void resume(int repetitions) {
private static long[] testPrintAllBrands() {
System.out.println("*** testPrintAllBrands");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
StringBuilder sb = new StringBuilder();
@@ -90,22 +90,22 @@ private static void resume(int repetitions) {
String brandsIterative = sb.substring(0, sb.length() - 2).toString();
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
String brands = joinFrom(db.getCars()).getBrand();
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testFindAllSalesOfAFerrari() {
System.out.println("*** testFindAllSalesOfAFerrari");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
List<Sale> salesIterative = new ArrayList<Sale>();
@@ -114,22 +114,22 @@ private static void resume(int repetitions) {
}
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
List<Sale> sales = select(db.getSales(), having(on(Sale.class).getCar().getBrand(), equalTo("Ferrari")));
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testFindAllBuysOfYoungestPerson() {
System.out.println("*** testFindAllBuysOfYoungestPerson");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
Person youngest = null;
@@ -142,22 +142,22 @@ private static void resume(int repetitions) {
}
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
List<Sale> sales = select(db.getSales(), having(on(Sale.class).getBuyer(), equalTo(selectMin(db.getPersons(), on(Person.class).getAge()))));
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testFindMostCostlySaleValue() {
System.out.println("*** testFindMostCostlySaleValue");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
double maxCost = 0.0;
@@ -167,22 +167,22 @@ private static void resume(int repetitions) {
}
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
double max = max(db.getSales(), on(Sale.class).getCost());
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testSumSalesCostWhereBothActorsAreAMale() {
System.out.println("*** testSumSalesCostWhereBothActorsAreAMale");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
double sumIterative = 0.0;
@@ -192,22 +192,22 @@ private static void resume(int repetitions) {
}
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
double sum = sum(select(db.getSales(), having(on(Sale.class).getBuyer().isMale()).and(having(on(Sale.class).getSeller().isMale()))), on(Sale.class).getCost());
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testFindYoungestAgeOfWhoBoughtACarForMoreThan50000() {
System.out.println("*** testFindYoungestAgeOfWhoBoughtACarForMoreThan50000");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
int ageIterative = Integer.MAX_VALUE;
@@ -220,22 +220,22 @@ private static void resume(int repetitions) {
}
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
int age = min(forEach(select(db.getSales(), having(on(Sale.class).getCost(), greaterThan(50000.00)))).getBuyer(), on(Person.class).getAge());
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testSortSalesByCost() {
System.out.println("*** testSortSalesByCost");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
List<Sale> sortedSalesIterative = new ArrayList<Sale>(db.getSales());
@@ -246,23 +246,23 @@ public int compare(Sale s1, Sale s2) {
});
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
List<Sale> sortedSales = sort(db.getSales(), on(Sale.class)
.getCost());
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testExtractCarsOriginalCost() {
System.out.println("*** testExtractCarsOriginalCost");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
List<Double> costsIterative = new ArrayList<Double>();
@@ -270,22 +270,22 @@ public int compare(Sale s1, Sale s2) {
costsIterative.add(car.getOriginalValue());
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
List<Double> costs = extract(db.getCars(), on(Car.class).getOriginalValue());
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testIndexCarsByBrand() {
System.out.println("*** testIndexCarsByBrand");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
Map<String, Car> carsByBrandIterative = new HashMap<String, Car>();
@@ -293,22 +293,22 @@ public int compare(Sale s1, Sale s2) {
carsByBrandIterative.put(car.getBrand(), car);
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
Map<String, Car> carsByBrand = index(db.getCars(), on(Car.class).getBrand());
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testGroupSalesByBuyersAndSellers() {
System.out.println("*** testGroupSalesByBuyersAndSellers");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
Person youngestPerson = null;
@@ -333,9 +333,9 @@ public int compare(Sale s1, Sale s2) {
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
Person youngest = selectMin(db.getPersons(), on(Person.class).getAge());
@@ -344,14 +344,14 @@ public int compare(Sale s1, Sale s2) {
Sale sale = group.findGroup(youngest).find(oldest).get(0);
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
private static long[] testFindMostBoughtCar() {
System.out.println("*** testFindMostBoughtCar");
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
Map<Car, Integer> carsBought = new LinkedHashMap<Car, Integer>();
@@ -371,9 +371,9 @@ public int compare(Sale s1, Sale s2) {
}
- long duration1 = System.currentTimeMillis() - start;
+ long duration1 = (System.nanoTime() - start) / 1000000;
System.out.println("iterative: " + duration1 + " msecs");
- start = System.currentTimeMillis();
+ start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
Group<Sale> group = selectMax(group(db.getSales(), by(on(Sale.class).getCar())).subgroups(), on(Group.class).getSize());
@@ -381,7 +381,7 @@ public int compare(Sale s1, Sale s2) {
int boughtTimes = group.getSize();
}
- long duration2 = System.currentTimeMillis() - start;
+ long duration2 = (System.nanoTime() - start) / 1000000;
System.out.println("lambdaj: " + duration2 + " msecs");
return new long[] {duration1, duration2};
}
View
2  src/test/java/ch/lambdaj/function/argument/InvocationSequenceTest.java
@@ -28,7 +28,7 @@ public void verifyEquals() throws NoSuchMethodException {
}
@Test
- public void sjekkProject() {
+ public void testProject() {
Collection<Car> cars = asList(new Car("Ford", "F150", 2011, 200));
assertThat(project(cars, SimpleBrand.class, on(Car.class)), hasItem(new SimpleBrand("Ford")));
assertThat(project(cars, SimpleBrand.class, on(Car.class).getBrand()), hasItem(new SimpleBrand("Ford")));
Please sign in to comment.
Something went wrong with that request. Please try again.