blob: b99f80f51916506a5346025927bc696cd817dc6e [file] [log] [blame]
/*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import test.java.lang.invoke.lib.Helper;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Enumeration containing information about methods from
* {@code j.l.i.MethodHandles} class that are used for testing lambda forms
* caching.
*
* @author kshefov
*/
public enum TestMethods {
FOLD_ARGUMENTS("foldArguments") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
data.put("modifierMHArgNum", modifierMHArgNum);
Class<?> combinerReturnType;
if (realArity == 0) {
combinerReturnType = void.class;
} else {
combinerReturnType = Helper.RNG.nextBoolean() ?
void.class : mtTarget.parameterType(0);
}
data.put("combinerReturnType", combinerReturnType);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodType mtTarget = (MethodType) data.get("mtTarget");
Class<?> combinerReturnType = (Class) data.get("combinerReturnType");
int modifierMHArgNum = (int) data.get("modifierMHArgNum");
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), kind);
Class<?> rType = mtTarget.returnType();
int combListStart = (combinerReturnType == void.class) ? 0 : 1;
if (modifierMHArgNum < combListStart) {
modifierMHArgNum = combListStart;
}
MethodHandle combiner = TestMethods.methodHandleGenerator(combinerReturnType,
mtTarget.parameterList().subList(combListStart,
modifierMHArgNum), kind);
return MethodHandles.foldArguments(target, combiner);
}
},
DROP_ARGUMENTS("dropArguments") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
int dropArgsPos = Helper.RNG.nextInt(realArity + 1);
data.put("dropArgsPos", dropArgsPos);
MethodType mtDropArgs = TestMethods.randomMethodTypeGenerator(
Helper.RNG.nextInt(super.maxArity - realArity));
data.put("mtDropArgs", mtDropArgs);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodType mtTarget = (MethodType) data.get("mtTarget");
MethodType mtDropArgs = (MethodType) data.get("mtDropArgs");
int dropArgsPos = (int) data.get("dropArgsPos");
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), kind);
int mtTgtSlotsCount = TestMethods.argSlotsCount(mtTarget);
int mtDASlotsCount = TestMethods.argSlotsCount(mtDropArgs);
List<Class<?>> fakeParList;
if (mtTgtSlotsCount + mtDASlotsCount > super.maxArity - 1) {
fakeParList = TestMethods.reduceArgListToSlotsCount(mtDropArgs.parameterList(),
super.maxArity - mtTgtSlotsCount - 1);
} else {
fakeParList = mtDropArgs.parameterList();
}
return MethodHandles.dropArguments(target, dropArgsPos, fakeParList);
}
},
EXPLICIT_CAST_ARGUMENTS("explicitCastArguments", Helper.MAX_ARITY / 2) {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
MethodType mtExcplCastArgs = TestMethods.randomMethodTypeGenerator(realArity);
if (mtTarget.returnType() == void.class) {
mtExcplCastArgs = MethodType.methodType(void.class,
mtExcplCastArgs.parameterArray());
}
if (mtExcplCastArgs.returnType() == void.class) {
mtExcplCastArgs = MethodType.methodType(mtTarget.returnType(),
mtExcplCastArgs.parameterArray());
}
data.put("mtExcplCastArgs", mtExcplCastArgs);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodType mtTarget = (MethodType) data.get("mtTarget");
MethodType mtExcplCastArgs = (MethodType) data.get("mtExcplCastArgs");
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), kind);
return MethodHandles.explicitCastArguments(target, mtExcplCastArgs);
}
},
FILTER_ARGUMENTS("filterArguments", Helper.MAX_ARITY / 2) {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
int filterArgsPos = Helper.RNG.nextInt(realArity + 1);
data.put("filterArgsPos", filterArgsPos);
int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos);
data.put("filtersArgsArrayLength", filtersArgsArrayLength);
MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength);
data.put("mtFilter", mtFilter);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodType mtTarget = (MethodType) data.get("mtTarget");
MethodType mtFilter = (MethodType) data.get("mtFilter");
int filterArgsPos = (int) data.get("filterArgsPos");
int filtersArgsArrayLength = (int) data.get("filtersArgsArrayLength");
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), kind);
MethodHandle[] filters = new MethodHandle[filtersArgsArrayLength];
for (int i = 0; i < filtersArgsArrayLength; i++) {
filters[i] = TestMethods.filterGenerator(mtFilter.parameterType(i),
mtTarget.parameterType(filterArgsPos + i), kind);
}
return MethodHandles.filterArguments(target, filterArgsPos, filters);
}
},
FILTER_RETURN_VALUE("filterReturnValue") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
int filterArgsPos = Helper.RNG.nextInt(realArity + 1);
int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos);
MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength);
data.put("mtFilter", mtFilter);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodType mtTarget = (MethodType) data.get("mtTarget");
MethodType mtFilter = (MethodType) data.get("mtFilter");
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), kind);
MethodHandle filter = TestMethods.filterGenerator(mtTarget.returnType(),
mtFilter.returnType(), kind);
return MethodHandles.filterReturnValue(target, filter);
}
},
INSERT_ARGUMENTS("insertArguments", Helper.MAX_ARITY - 3) {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
int insertArgsPos = Helper.RNG.nextInt(realArity + 1);
data.put("insertArgsPos", insertArgsPos);
int insertArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - insertArgsPos);
MethodType mtInsertArgs = MethodType.methodType(void.class, mtTarget.parameterList()
.subList(insertArgsPos, insertArgsPos + insertArgsArrayLength));
data.put("mtInsertArgs", mtInsertArgs);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodType mtTarget = (MethodType) data.get("mtTarget");
MethodType mtInsertArgs = (MethodType) data.get("mtInsertArgs");
int insertArgsPos = (int) data.get("insertArgsPos");
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), kind);
Object[] insertList = Helper.randomArgs(mtInsertArgs.parameterList());
return MethodHandles.insertArguments(target, insertArgsPos, insertList);
}
},
PERMUTE_ARGUMENTS("permuteArguments", Helper.MAX_ARITY / 2) {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
int[] permuteArgsReorderArray = new int[realArity];
int mtPermuteArgsNum = Helper.RNG.nextInt(Helper.MAX_ARITY);
mtPermuteArgsNum = mtPermuteArgsNum == 0 ? 1 : mtPermuteArgsNum;
MethodType mtPermuteArgs = TestMethods.randomMethodTypeGenerator(mtPermuteArgsNum);
mtTarget = mtTarget.changeReturnType(mtPermuteArgs.returnType());
for (int i = 0; i < realArity; i++) {
int mtPermuteArgsParNum = Helper.RNG.nextInt(mtPermuteArgs.parameterCount());
permuteArgsReorderArray[i] = mtPermuteArgsParNum;
mtTarget = mtTarget.changeParameterType(
i, mtPermuteArgs.parameterType(mtPermuteArgsParNum));
}
data.put("mtTarget", mtTarget);
data.put("permuteArgsReorderArray", permuteArgsReorderArray);
data.put("mtPermuteArgs", mtPermuteArgs);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodType mtTarget = (MethodType) data.get("mtTarget");
MethodType mtPermuteArgs = (MethodType) data.get("mtPermuteArgs");
int[] permuteArgsReorderArray = (int[]) data.get("permuteArgsReorderArray");
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), kind);
return MethodHandles.permuteArguments(target, mtPermuteArgs, permuteArgsReorderArray);
}
},
THROW_EXCEPTION("throwException") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
MethodType mtTarget = (MethodType) data.get("mtTarget");
Class<?> rType = mtTarget.returnType();
return MethodHandles.throwException(rType, Exception.class
);
}
},
GUARD_WITH_TEST("guardWithTest") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
data.put("modifierMHArgNum", modifierMHArgNum);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodType mtTarget = (MethodType) data.get("mtTarget");
int modifierMHArgNum = (int) data.get("modifierMHArgNum");
TestMethods.Kind targetKind;
TestMethods.Kind fallbackKind;
if (kind.equals(TestMethods.Kind.ONE)) {
targetKind = TestMethods.Kind.ONE;
fallbackKind = TestMethods.Kind.TWO;
} else {
targetKind = TestMethods.Kind.TWO;
fallbackKind = TestMethods.Kind.ONE;
}
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), targetKind);
MethodHandle fallback = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), fallbackKind);
MethodHandle test = TestMethods.methodHandleGenerator(boolean.class,
mtTarget.parameterList().subList(0, modifierMHArgNum), kind);
return MethodHandles.guardWithTest(test, target, fallback);
}
},
CATCH_EXCEPTION("catchException") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
data.put("modifierMHArgNum", modifierMHArgNum);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodType mtTarget = (MethodType) data.get("mtTarget");
int modifierMHArgNum = (int) data.get("modifierMHArgNum");
MethodHandle target;
if (kind.equals(TestMethods.Kind.ONE)) {
target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), TestMethods.Kind.ONE);
} else {
target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
mtTarget.parameterList(), TestMethods.Kind.EXCEPT);
}
List<Class<?>> handlerParamList = new ArrayList<>(mtTarget.parameterCount() + 1);
handlerParamList.add(Exception.class);
handlerParamList.addAll(mtTarget.parameterList().subList(0, modifierMHArgNum));
MethodHandle handler = TestMethods.methodHandleGenerator(
mtTarget.returnType(), handlerParamList, TestMethods.Kind.TWO);
return MethodHandles.catchException(target, Exception.class, handler);
}
},
INVOKER("invoker", Helper.MAX_ARITY - 1) {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
MethodType mtTarget = (MethodType) data.get("mtTarget");
return MethodHandles.invoker(mtTarget);
}
},
EXACT_INVOKER("exactInvoker", Helper.MAX_ARITY - 1) {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
MethodType mtTarget = (MethodType) data.get("mtTarget");
return MethodHandles.exactInvoker(mtTarget);
}
},
SPREAD_INVOKER("spreadInvoker", Helper.MAX_ARITY - 1) {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
// Arity after reducing because of long and double take 2 slots.
int realArity = mtTarget.parameterCount();
int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
data.put("modifierMHArgNum", modifierMHArgNum);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
MethodType mtTarget = (MethodType) data.get("mtTarget");
int modifierMHArgNum = (int) data.get("modifierMHArgNum");
return MethodHandles.spreadInvoker(mtTarget, modifierMHArgNum);
}
},
ARRAY_ELEMENT_GETTER("arrayElementGetter") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
MethodType mtTarget = (MethodType) data.get("mtTarget");
Class<?> rType = mtTarget.returnType();
if (rType == void.class) {
rType = Object.class;
}
return MethodHandles.arrayElementGetter(Array.newInstance(rType, 2).getClass());
}
},
ARRAY_ELEMENT_SETTER("arrayElementSetter") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
MethodType mtTarget = (MethodType) data.get("mtTarget");
Class<?> rType = mtTarget.returnType();
if (rType == void.class) {
rType = Object.class;
}
return MethodHandles.arrayElementSetter(Array.newInstance(rType, 2).getClass());
}
},
CONSTANT("constant") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
MethodType mtTarget = (MethodType) data.get("mtTarget");
Class<?> rType = mtTarget.returnType();
if (rType == void.class) {
rType = Object.class;
}
if (rType.equals(boolean.class)) {
// There should be the same return values because for default values there are special "zero" forms
return MethodHandles.constant(rType, true);
} else {
return MethodHandles.constant(rType, kind.getValue(rType));
}
}
},
IDENTITY("identity") {
@Override
public Map<String, Object> getTestCaseData() {
Map<String, Object> data = new HashMap<>();
int desiredArity = Helper.RNG.nextInt(super.maxArity);
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
data.put("mtTarget", mtTarget);
return data;
}
@Override
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
MethodType mtTarget = (MethodType) data.get("mtTarget");
Class<?> rType = mtTarget.returnType();
if (rType == void.class) {
rType = Object.class;
}
return MethodHandles.identity(rType);
}
};
/**
* Test method's name.
*/
public final String name;
private final int maxArity;
private TestMethods(String name, int maxArity) {
this.name = name;
this.maxArity = maxArity;
}
private TestMethods(String name) {
this(name, Helper.MAX_ARITY);
}
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
throw new UnsupportedOperationException(
"TESTBUG: getMH method is not implemented for test method " + this);
}
/**
* Creates an adapter method handle depending on a test method from
* MethodHandles class. Adapter is what is returned by the test method. This
* method is able to create two kinds of adapters, their type will be the
* same, but return values are different.
*
* @param data a Map containing data to create a method handle, can be
* obtained by {@link #getTestCaseData} method
* @param kind defines whether adapter ONE or adapter TWO will be
* initialized. Should be equal to TestMethods.Kind.ONE or
* TestMethods.Kind.TWO
* @return Method handle adapter that behaves according to
* TestMethods.Kind.ONE or TestMethods.Kind.TWO
* @throws java.lang.NoSuchMethodException
* @throws java.lang.IllegalAccessException
*/
public MethodHandle getTestCaseMH(Map<String, Object> data, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
if (data == null) {
throw new Error(String.format("TESTBUG: Data for test method %s is not prepared",
this.name));
}
if (!kind.equals(TestMethods.Kind.ONE) && !kind.equals(TestMethods.Kind.TWO)) {
throw new IllegalArgumentException("TESTBUG: Wrong \"kind\" (" + kind
+ ") arg to getTestCaseMH function."
+ " Should be Kind.ONE or Kind.TWO");
}
return getMH(data, kind);
}
/**
* Returns a data Map needed for {@link #getTestCaseMH} method.
*
* @return data Map needed for {@link #getTestCaseMH} method
*/
public Map<String, Object> getTestCaseData() {
throw new UnsupportedOperationException(
"TESTBUG: getTestCaseData method is not implemented for test method " + this);
}
/**
* Enumeration used in methodHandleGenerator to define whether a MH returned
* by this method returns "2" in different type representations, "4", or
* throw an Exception.
*/
public static enum Kind {
ONE(2),
TWO(4),
EXCEPT(0);
private final int value;
private Object getValue(Class<?> cl) {
return Helper.castToWrapper(value, cl);
}
private MethodHandle getBasicMH(Class<?> rType)
throws NoSuchMethodException, IllegalAccessException {
MethodHandle result = null;
switch (this) {
case ONE:
case TWO:
if (rType.equals(void.class)) {
result = MethodHandles.lookup().findVirtual(Kind.class,
"returnVoid", MethodType.methodType(void.class));
result = MethodHandles.insertArguments(result, 0, this);
} else {
result = MethodHandles.constant(rType, getValue(rType));
}
break;
case EXCEPT:
result = MethodHandles.throwException(rType, Exception.class);
result = MethodHandles.insertArguments(result, 0, new Exception());
break;
}
return result;
}
private void returnVoid() {
}
private Kind(int value) {
this.value = value;
}
}
/**
* Routine used to obtain a randomly generated method type.
*
* @param arity Arity of returned method type.
* @return MethodType generated randomly.
*/
private static MethodType randomMethodTypeGenerator(int arity) {
return Helper.randomMethodTypeGenerator(arity);
}
/**
* Routine used to obtain a method handles of a given type an kind (return
* value).
*
* @param returnType Type of MH return value.
* @param argTypes Types of MH args.
* @param kind Defines whether the obtained MH returns "1" or "2".
* @return Method handle of the given type.
* @throws NoSuchMethodException
* @throws IllegalAccessException
*/
private static MethodHandle methodHandleGenerator(Class<?> returnType,
List<Class<?>> argTypes, TestMethods.Kind kind)
throws NoSuchMethodException, IllegalAccessException {
MethodHandle result;
result = kind.getBasicMH(returnType);
return Helper.addTrailingArgs(result, argTypes.size(), argTypes);
}
/**
* Routine that generates filter method handles to test
* MethodHandles.filterArguments method.
*
* @param inputType Filter's argument type.
* @param returnType Filter's return type.
* @param kind Filter's return value definer.
* @return A filter method handle, that takes one argument.
* @throws NoSuchMethodException
* @throws IllegalAccessException
*/
private static MethodHandle filterGenerator(Class<?> inputType, Class<?> returnType,
TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
MethodHandle tmpMH = kind.getBasicMH(returnType);
if (inputType.equals(void.class)) {
return tmpMH;
}
ArrayList<Class<?>> inputTypeList = new ArrayList<>(1);
inputTypeList.add(inputType);
return Helper.addTrailingArgs(tmpMH, 1, inputTypeList);
}
private static int argSlotsCount(MethodType mt) {
int result = 0;
for (Class cl : mt.parameterArray()) {
if (cl.equals(long.class) || cl.equals(double.class)) {
result += 2;
} else {
result++;
}
}
return result;
}
private static List<Class<?>> reduceArgListToSlotsCount(List<Class<?>> list,
int desiredSlotCount) {
List<Class<?>> result = new ArrayList<>(desiredSlotCount);
int count = 0;
for (Class<?> cl : list) {
if (count >= desiredSlotCount) {
break;
}
if (cl.equals(long.class) || cl.equals(double.class)) {
count += 2;
} else {
count++;
}
result.add(cl);
}
return result;
}
}