/* * 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.facebook.presto.spi.block; import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; import java.util.Objects; import static com.facebook.presto.spi.block.MethodHandleUtil.compose; import static com.facebook.presto.spi.block.MethodHandleUtil.methodHandle; import static com.google.common.base.MoreObjects.toStringHelper; import static org.testng.Assert.assertEquals; public class TestMethodHandleUtil { // Each custom type in this test is effectively a number. // All method handles in this test returns the product of all input parameters. // Each method handles has distinct input types and return type. // The composed function is invoked once to verify that: // * The composed function type is expected // * Each argument is multiplied into the product exactly once. (by using prime numbers as input) @Test public void testCompose2() throws Throwable { MethodHandle fUS2R = methodHandle(TestMethodHandleUtil.class, "fUS2R", U.class, S1.class, S2.class); MethodHandle fT2U = methodHandle(TestMethodHandleUtil.class, "fT2U", T1.class, T2.class); MethodHandle composed = compose(fUS2R, fT2U); assertEquals((R) composed.invokeExact(new T1(2), new T2(3), new S1(5), new S2(7)), new R(210)); } @Test public void testCompose2withoutS() throws Throwable { MethodHandle fU2R = methodHandle(TestMethodHandleUtil.class, "fU2R", U.class); MethodHandle fT2U = methodHandle(TestMethodHandleUtil.class, "fT2U", T1.class, T2.class); MethodHandle composed = compose(fU2R, fT2U); assertEquals((R) composed.invokeExact(new T1(2), new T2(3)), new R(6)); } @Test public void testCompose3() throws Throwable { MethodHandle fUV2R = methodHandle(TestMethodHandleUtil.class, "fUV2R", U.class, V.class); MethodHandle fS2U = methodHandle(TestMethodHandleUtil.class, "fS2U", S1.class, S2.class); MethodHandle fT2V = methodHandle(TestMethodHandleUtil.class, "fT2V", T1.class, T2.class); MethodHandle composed = compose(fUV2R, fS2U, fT2V); assertEquals((R) composed.invokeExact(new S1(2), new S2(3), new T1(5), new T2(7)), new R(210)); } public static R fU2R(U u) { return new R(u.getValue()); } public static R fUS2R(U u, S1 s1, S2 s2) { return new R(u.getValue() * s1.getValue() * s2.getValue()); } public static R fUV2R(U u, V v) { return new R(u.getValue() * v.getValue()); } public static U fT2U(T1 t1, T2 t2) { return new U(t1.getValue() * t2.getValue()); } public static U fS2U(S1 s1, S2 s2) { return new U(s1.getValue() * s2.getValue()); } public static V fT2V(T1 t1, T2 t2) { return new V(t1.getValue() * t2.getValue()); } public static String squareBracket(String s) { return "[" + s + "]"; } public static String squareBracket(String s, double d) { return "[" + s + "," + ((long) d) + "]"; } public static String curlyBracket(String s, char c) { return "{" + s + "=" + c + "}"; } public static double sum(long x, int c) { return (double) x + c; } private static class Base { private final int value; public Base(int value) { this.value = value; } public int getValue() { return value; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Base base = (Base) o; return value == base.value; } @Override public int hashCode() { return Objects.hash(value); } @Override public String toString() { return toStringHelper(this) .add("value", value) .toString(); } } private static class U extends Base { public U(int value) { super(value); } } private static class V extends Base { public V(int value) { super(value); } } private static class R extends Base { public R(int value) { super(value); } } private static class S1 extends Base { public S1(int value) { super(value); } } private static class S2 extends Base { public S2(int value) { super(value); } } private static class T1 extends Base { public T1(int value) { super(value); } } private static class T2 extends Base { public T2(int value) { super(value); } } }