/*
* 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);
}
}
}