Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
b9fd5a85
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
b9fd5a85
编写于
9月 12, 2014
作者:
K
kshefov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8057719: Develop new tests for LambdaForm Reduction and Caching feature
Reviewed-by: iignatyev, vlivanov, psandoz
上级
5cf2c79c
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
1184 addition
and
0 deletion
+1184
-0
test/java/lang/invoke/LFCaching/LFCachingTestCase.java
test/java/lang/invoke/LFCaching/LFCachingTestCase.java
+78
-0
test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java
test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java
+102
-0
test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java
.../java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java
+111
-0
test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java
...java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java
+78
-0
test/java/lang/invoke/LFCaching/LambdaFormTestCase.java
test/java/lang/invoke/LFCaching/LambdaFormTestCase.java
+117
-0
test/java/lang/invoke/LFCaching/TestMethods.java
test/java/lang/invoke/LFCaching/TestMethods.java
+698
-0
未找到文件。
test/java/lang/invoke/LFCaching/LFCachingTestCase.java
0 → 100644
浏览文件 @
b9fd5a85
/*
* Copyright (c) 2014, 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
java.lang.invoke.MethodHandle
;
import
java.lang.reflect.InvocationTargetException
;
/**
* Abstract class for lambda forms caching testing.
*
* @author kshefov
*/
public
abstract
class
LFCachingTestCase
extends
LambdaFormTestCase
{
/**
* Constructor for lambda forms caching test case.
*
* @param testMethod A method from {@code j.l.i.MethodHandles} class that
* returns a {@code j.l.i.MethodHandle} instance.
*/
protected
LFCachingTestCase
(
TestMethods
testMethod
)
{
super
(
testMethod
);
}
/**
* Checks that the lambda forms of the two adapter method handles adapter1
* and adapter2 are the same.
*
* @param adapter1 First method handle.
* @param adapter2 Second method handle.
*/
public
void
checkLFCaching
(
MethodHandle
adapter1
,
MethodHandle
adapter2
)
{
try
{
if
(!
adapter1
.
type
().
equals
(
adapter2
.
type
()))
{
throw
new
Error
(
"TESTBUG: Types of the two method handles are not the same"
);
}
Object
lambdaForm0
=
LambdaFormTestCase
.
INTERNAL_FORM
.
invoke
(
adapter1
);
Object
lambdaForm1
=
LambdaFormTestCase
.
INTERNAL_FORM
.
invoke
(
adapter2
);
if
(
lambdaForm0
==
null
||
lambdaForm1
==
null
)
{
throw
new
Error
(
"Unexpected error: One or both lambda forms of the method handles are null"
);
}
if
(
lambdaForm0
!=
lambdaForm1
)
{
System
.
err
.
println
(
"Lambda form 0 toString is:"
);
System
.
err
.
println
(
lambdaForm0
);
System
.
err
.
println
(
"Lambda form 1 toString is:"
);
System
.
err
.
println
(
lambdaForm1
);
throw
new
AssertionError
(
"Error: Lambda forms of the two method handles"
+
" are not the same. LF cahing does not work"
);
}
}
catch
(
IllegalAccessException
|
IllegalArgumentException
|
SecurityException
|
InvocationTargetException
ex
)
{
throw
new
Error
(
"Unexpected exception: "
,
ex
);
}
}
}
test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java
0 → 100644
浏览文件 @
b9fd5a85
/*
* Copyright (c) 2014, 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.
*/
/*
* @test LFGarbageCollectedTest
* @bug 8046703
* @summary Test verifies that lambda forms are garbage collected
* @author kshefov
* @library /lib/testlibrary/jsr292 /lib/testlibrary
* @build TestMethods
* @build LambdaFormTestCase
* @build LFGarbageCollectedTest
* @run main/othervm/timeout=600 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true -DtestLimit=150 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI LFGarbageCollectedTest
*/
import
java.lang.invoke.MethodHandle
;
import
java.lang.ref.PhantomReference
;
import
java.lang.ref.ReferenceQueue
;
import
java.lang.reflect.InvocationTargetException
;
import
java.util.Arrays
;
import
java.util.EnumSet
;
import
java.util.Map
;
/**
* Lambda forms garbage collection test class.
*/
public
final
class
LFGarbageCollectedTest
extends
LambdaFormTestCase
{
/**
* Constructor for a lambda forms garbage collection test case.
*
* @param testMethod A method from {@code j.l.i.MethodHandles} class that
* returns a {@code j.l.i.MethodHandle} instance.
*/
public
LFGarbageCollectedTest
(
TestMethods
testMethod
)
{
super
(
testMethod
);
}
@Override
public
void
doTest
()
{
try
{
Map
<
String
,
Object
>
data
=
getTestMethod
().
getTestCaseData
();
MethodHandle
adapter
;
try
{
adapter
=
getTestMethod
().
getTestCaseMH
(
data
,
TestMethods
.
Kind
.
ONE
);
}
catch
(
NoSuchMethodException
ex
)
{
throw
new
Error
(
"Unexpected exception: "
,
ex
);
}
Object
lambdaForm
=
LambdaFormTestCase
.
INTERNAL_FORM
.
invoke
(
adapter
);
if
(
lambdaForm
==
null
)
{
throw
new
Error
(
"Unexpected error: Lambda form of the method handle is null"
);
}
ReferenceQueue
rq
=
new
ReferenceQueue
();
PhantomReference
ph
=
new
PhantomReference
(
lambdaForm
,
rq
);
lambdaForm
=
null
;
data
=
null
;
adapter
=
null
;
for
(
int
i
=
0
;
i
<
1000
&&
!
ph
.
isEnqueued
();
i
++)
{
System
.
gc
();
}
if
(!
ph
.
isEnqueued
())
{
throw
new
AssertionError
(
"Error: Lambda form is not garbage collected"
);
}
}
catch
(
IllegalAccessException
|
IllegalArgumentException
|
InvocationTargetException
ex
)
{
throw
new
Error
(
"Unexpected exception: "
,
ex
);
}
}
/**
* Main routine for lambda forms garbage collection test.
*
* @param args Accepts no arguments.
*/
public
static
void
main
(
String
[]
args
)
{
// The "identity" and "constant" methods should be removed from this test,
// because their lambda forms are stored in a static filed and are not GC'ed.
// There can be only 5 such LFs for each method, so no memory leak happens.
EnumSet
<
TestMethods
>
testMethods
=
EnumSet
.
complementOf
(
EnumSet
.
of
(
TestMethods
.
IDENTITY
,
TestMethods
.
CONSTANT
));
LambdaFormTestCase
.
runTests
(
LFGarbageCollectedTest:
:
new
,
testMethods
);
}
}
test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java
0 → 100644
浏览文件 @
b9fd5a85
/*
* Copyright (c) 2014, 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.
*/
/*
* @test LFMultiThreadCachingTest
* @bug 8046703
* @summary Test verifies that lambda forms are cached when run with multiple threads
* @author kshefov
* @library /lib/testlibrary/jsr292 /lib/testlibrary
* @build TestMethods
* @build LambdaFormTestCase
* @build LFCachingTestCase
* @build LFMultiThreadCachingTest
* @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFMultiThreadCachingTest
*/
import
java.lang.invoke.MethodHandle
;
import
java.util.EnumSet
;
import
java.util.Map
;
import
java.util.concurrent.BrokenBarrierException
;
import
java.util.concurrent.ConcurrentLinkedQueue
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.CyclicBarrier
;
/**
* Multiple threaded lambda forms caching test class.
*/
public
final
class
LFMultiThreadCachingTest
extends
LFCachingTestCase
{
private
static
final
TestMethods
.
Kind
[]
KINDS
;
static
{
EnumSet
<
TestMethods
.
Kind
>
set
=
EnumSet
.
complementOf
(
EnumSet
.
of
(
TestMethods
.
Kind
.
EXCEPT
));
KINDS
=
set
.
toArray
(
new
TestMethods
.
Kind
[
set
.
size
()]);
if
(
KINDS
.
length
<
2
)
{
throw
new
Error
(
"TESTBUG: KINDS.length["
+
KINDS
.
length
+
"] should be at least 2"
);
}
}
private
static
final
int
CORES
=
Math
.
max
(
KINDS
.
length
,
Runtime
.
getRuntime
().
availableProcessors
());
/**
* Constructor a for multiple threaded lambda forms caching test case.
*
* @param testMethod A method from {@code j.l.i.MethodHandles} class that
* returns a {@code j.l.i.MethodHandle} instance.
*/
public
LFMultiThreadCachingTest
(
TestMethods
testMethod
)
{
super
(
testMethod
);
}
@Override
public
void
doTest
()
{
Map
<
String
,
Object
>
data
=
getTestMethod
().
getTestCaseData
();
ConcurrentLinkedQueue
<
MethodHandle
>
adapters
=
new
ConcurrentLinkedQueue
<>();
CyclicBarrier
begin
=
new
CyclicBarrier
(
CORES
);
CountDownLatch
end
=
new
CountDownLatch
(
CORES
);
for
(
int
i
=
0
;
i
<
CORES
;
++
i
)
{
TestMethods
.
Kind
kind
=
KINDS
[
i
%
KINDS
.
length
];
new
Thread
(()
->
{
try
{
begin
.
await
();
adapters
.
add
(
getTestMethod
().
getTestCaseMH
(
data
,
kind
));
}
catch
(
InterruptedException
|
BrokenBarrierException
|
IllegalAccessException
|
NoSuchMethodException
ex
)
{
throw
new
Error
(
"Unexpected exception: "
,
ex
);
}
finally
{
end
.
countDown
();
}
}).
start
();
}
try
{
end
.
await
();
}
catch
(
InterruptedException
ex
)
{
throw
new
Error
(
"Unexpected exception: "
,
ex
);
}
if
(
adapters
.
size
()
<
CORES
)
{
throw
new
Error
(
"adapters size["
+
adapters
.
size
()
+
"] is less than "
+
CORES
);
}
MethodHandle
prev
=
adapters
.
poll
();
for
(
MethodHandle
current
:
adapters
)
{
checkLFCaching
(
prev
,
current
);
prev
=
current
;
}
}
/**
* Main routine for multiple threaded lambda forms caching test.
*
* @param args Accepts no arguments.
*/
public
static
void
main
(
String
[]
args
)
{
LambdaFormTestCase
.
runTests
(
LFMultiThreadCachingTest:
:
new
,
EnumSet
.
allOf
(
TestMethods
.
class
));
}
}
test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java
0 → 100644
浏览文件 @
b9fd5a85
/*
* Copyright (c) 2014, 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.
*/
/*
* @test LFSingleThreadCachingTest
* @bug 8046703
* @summary Test verifies that lambda forms are cached when run with single thread
* @author kshefov
* @library /lib/testlibrary/jsr292 /lib/testlibrary
* @build TestMethods
* @build LambdaFormTestCase
* @build LFCachingTestCase
* @build LFSingleThreadCachingTest
* @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFSingleThreadCachingTest
*/
import
java.lang.invoke.MethodHandle
;
import
java.util.EnumSet
;
import
java.util.Map
;
/**
* Single threaded lambda forms caching test class.
*/
public
final
class
LFSingleThreadCachingTest
extends
LFCachingTestCase
{
/**
* Constructor for a single threaded lambda forms caching test case.
*
* @param testMethod A method from {@code j.l.i.MethodHandles} class that
* returns a {@code j.l.i.MethodHandle} instance.
*/
public
LFSingleThreadCachingTest
(
TestMethods
testMethod
)
{
super
(
testMethod
);
}
@Override
public
void
doTest
()
{
MethodHandle
adapter1
;
MethodHandle
adapter2
;
Map
<
String
,
Object
>
data
=
getTestMethod
().
getTestCaseData
();
try
{
adapter1
=
getTestMethod
().
getTestCaseMH
(
data
,
TestMethods
.
Kind
.
ONE
);
adapter2
=
getTestMethod
().
getTestCaseMH
(
data
,
TestMethods
.
Kind
.
TWO
);
}
catch
(
NoSuchMethodException
|
IllegalAccessException
ex
)
{
throw
new
Error
(
"Unexpected exception: "
,
ex
);
}
checkLFCaching
(
adapter1
,
adapter2
);
}
/**
* Main routine for single threaded lambda forms caching test.
*
* @param args Accepts no arguments.
*/
public
static
void
main
(
String
[]
args
)
{
LambdaFormTestCase
.
runTests
(
LFSingleThreadCachingTest:
:
new
,
EnumSet
.
allOf
(
TestMethods
.
class
));
}
}
test/java/lang/invoke/LFCaching/LambdaFormTestCase.java
0 → 100644
浏览文件 @
b9fd5a85
/*
* Copyright (c) 2014, 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
com.oracle.testlibrary.jsr292.Helper
;
import
java.lang.reflect.Method
;
import
java.util.Collection
;
import
java.util.function.Function
;
/**
* Lambda forms caching test case class. Contains all necessary test routines to
* test lambda forms caching in method handles returned by methods of
* MethodHandles class.
*
* @author kshefov
*/
public
abstract
class
LambdaFormTestCase
{
private
final
static
String
METHOD_HANDLE_CLASS_NAME
=
"java.lang.invoke.MethodHandle"
;
private
final
static
String
INTERNAL_FORM_METHOD_NAME
=
"internalForm"
;
/**
* Reflection link to {@code j.l.i.MethodHandle.internalForm} method. It is
* used to get a lambda form from a method handle.
*/
protected
final
static
Method
INTERNAL_FORM
;
static
{
try
{
Class
mhClass
=
Class
.
forName
(
METHOD_HANDLE_CLASS_NAME
);
INTERNAL_FORM
=
mhClass
.
getDeclaredMethod
(
INTERNAL_FORM_METHOD_NAME
);
INTERNAL_FORM
.
setAccessible
(
true
);
}
catch
(
Exception
ex
)
{
throw
new
Error
(
"Unexpected exception: "
,
ex
);
}
}
private
final
TestMethods
testMethod
;
/**
* Test case constructor. Generates test cases with random method types for
* given methods form {@code j.l.i.MethodHandles} class.
*
* @param testMethod A method from {@code j.l.i.MethodHandles} class which
* returns a {@code j.l.i.MethodHandle}.
*/
protected
LambdaFormTestCase
(
TestMethods
testMethod
)
{
this
.
testMethod
=
testMethod
;
}
public
TestMethods
getTestMethod
()
{
return
testMethod
;
}
/**
* Routine that executes a test case.
*/
public
abstract
void
doTest
();
/**
* Runs a number of test cases defined by the size of testCases list.
*
* @param ctor constructor of LambdaFormCachingTest or its child classes
* object.
* @param testMethods list of test methods
*/
public
static
void
runTests
(
Function
<
TestMethods
,
LambdaFormTestCase
>
ctor
,
Collection
<
TestMethods
>
testMethods
)
{
boolean
passed
=
true
;
int
testCounter
=
0
;
int
failCounter
=
0
;
long
iterations
=
Math
.
max
(
1
,
Helper
.
TEST_LIMIT
/
testMethods
.
size
());
for
(
long
i
=
0
;
i
<
iterations
;
i
++)
{
System
.
err
.
println
(
String
.
format
(
"Iteration %d:"
,
i
));
for
(
TestMethods
testMethod
:
testMethods
)
{
LambdaFormTestCase
testCase
=
ctor
.
apply
(
testMethod
);
try
{
System
.
err
.
printf
(
"Tested LF caching feature with MethodHandles.%s method.%n"
,
testCase
.
getTestMethod
().
name
);
testCase
.
doTest
();
System
.
err
.
println
(
"PASSED"
);
}
catch
(
Throwable
t
)
{
t
.
printStackTrace
();
System
.
err
.
println
(
"FAILED"
);
passed
=
false
;
failCounter
++;
}
testCounter
++;
}
}
if
(!
passed
)
{
throw
new
Error
(
String
.
format
(
"%d of %d test cases FAILED! %n"
+
"Rerun the test with the same \"-Dseed=\" option as in the log file!"
,
failCounter
,
testCounter
));
}
else
{
System
.
err
.
println
(
String
.
format
(
"All %d test cases PASSED!"
,
testCounter
));
}
}
}
test/java/lang/invoke/LFCaching/TestMethods.java
0 → 100644
浏览文件 @
b9fd5a85
/*
* Copyright (c) 2014, 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
com.oracle.testlibrary.jsr292.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
(
Helper
.
MAX_ARITY
);
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
(
Helper
.
MAX_ARITY
);
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
(
Helper
.
MAX_ARITY
-
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
>
Helper
.
MAX_ARITY
-
1
)
{
fakeParList
=
TestMethods
.
reduceArgListToSlotsCount
(
mtDropArgs
.
parameterList
(),
Helper
.
MAX_ARITY
-
mtTgtSlotsCount
-
1
);
}
else
{
fakeParList
=
mtDropArgs
.
parameterList
();
}
return
MethodHandles
.
dropArguments
(
target
,
dropArgsPos
,
fakeParList
);
}
},
EXPLICIT_CAST_ARGUMENTS
(
"explicitCastArguments"
)
{
@Override
public
Map
<
String
,
Object
>
getTestCaseData
()
{
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
int
desiredArity
=
Helper
.
RNG
.
nextInt
(
Helper
.
MAX_ARITY
/
2
);
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"
)
{
@Override
public
Map
<
String
,
Object
>
getTestCaseData
()
{
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
int
desiredArity
=
Helper
.
RNG
.
nextInt
(
Helper
.
MAX_ARITY
/
2
);
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
(
Helper
.
MAX_ARITY
);
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"
)
{
@Override
public
Map
<
String
,
Object
>
getTestCaseData
()
{
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
int
desiredArity
=
Helper
.
RNG
.
nextInt
(
Helper
.
MAX_ARITY
);
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"
)
{
@Override
public
Map
<
String
,
Object
>
getTestCaseData
()
{
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
int
desiredArity
=
Helper
.
RNG
.
nextInt
(
Helper
.
MAX_ARITY
/
2
);
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
mtParmuteArgsNum
=
Helper
.
RNG
.
nextInt
(
Helper
.
MAX_ARITY
);
mtParmuteArgsNum
=
mtParmuteArgsNum
==
0
?
1
:
mtParmuteArgsNum
;
MethodType
mtPermuteArgs
=
TestMethods
.
randomMethodTypeGenerator
(
mtParmuteArgsNum
);
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
(
Helper
.
MAX_ARITY
);
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
(
Helper
.
MAX_ARITY
);
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
(
Helper
.
MAX_ARITY
);
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"
)
{
@Override
public
Map
<
String
,
Object
>
getTestCaseData
()
{
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
int
desiredArity
=
Helper
.
RNG
.
nextInt
(
Helper
.
MAX_ARITY
);
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"
)
{
@Override
public
Map
<
String
,
Object
>
getTestCaseData
()
{
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
int
desiredArity
=
Helper
.
RNG
.
nextInt
(
Helper
.
MAX_ARITY
);
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"
)
{
@Override
public
Map
<
String
,
Object
>
getTestCaseData
()
{
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
int
desiredArity
=
Helper
.
RNG
.
nextInt
(
Helper
.
MAX_ARITY
);
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
(
Helper
.
MAX_ARITY
);
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
(
Helper
.
MAX_ARITY
);
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
(
Helper
.
MAX_ARITY
);
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
(
Helper
.
MAX_ARITY
);
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
TestMethods
(
String
name
)
{
this
.
name
=
name
;
}
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
)
{
final
Class
<?>[]
CLASSES
=
{
Object
.
class
,
int
.
class
,
boolean
.
class
,
byte
.
class
,
short
.
class
,
char
.
class
,
long
.
class
,
float
.
class
,
double
.
class
};
if
(
arity
>
Helper
.
MAX_ARITY
)
{
throw
new
IllegalArgumentException
(
String
.
format
(
"Arity should not exceed %d!"
,
Helper
.
MAX_ARITY
));
}
List
<
Class
<?>>
list
=
Helper
.
randomClasses
(
CLASSES
,
arity
);
list
=
Helper
.
getParams
(
list
,
false
,
arity
);
int
i
=
Helper
.
RNG
.
nextInt
(
CLASSES
.
length
+
1
);
Class
<?>
rtype
=
i
==
CLASSES
.
length
?
void
.
class
:
CLASSES
[
i
];
return
MethodType
.
methodType
(
rtype
,
list
);
}
/**
* 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
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录