/*
* 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;
}
}
Messung V0.5 in Prozent C=98 H=89 G=93
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-10-01)
¤
*© Formatika GbR, Deutschland