Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-aarch32-jdk8u
Path: blob/jdk8u272-b10-aarch32-20201026/jdk/test/java/lang/invoke/LFCaching/TestMethods.java
48795 views
1
/*
2
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import com.oracle.testlibrary.jsr292.Helper;
25
import java.lang.invoke.MethodHandle;
26
import java.lang.invoke.MethodHandles;
27
import java.lang.invoke.MethodType;
28
import java.lang.reflect.Array;
29
import java.util.ArrayList;
30
import java.util.HashMap;
31
import java.util.List;
32
import java.util.Map;
33
34
/**
35
* Enumeration containing information about methods from
36
* {@code j.l.i.MethodHandles} class that are used for testing lambda forms
37
* caching.
38
*
39
* @author kshefov
40
*/
41
public enum TestMethods {
42
43
FOLD_ARGUMENTS("foldArguments") {
44
@Override
45
public Map<String, Object> getTestCaseData() {
46
Map<String, Object> data = new HashMap<>();
47
int desiredArity = Helper.RNG.nextInt(super.maxArity);
48
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
49
data.put("mtTarget", mtTarget);
50
// Arity after reducing because of long and double take 2 slots.
51
int realArity = mtTarget.parameterCount();
52
int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
53
data.put("modifierMHArgNum", modifierMHArgNum);
54
Class<?> combinerReturnType;
55
if (realArity == 0) {
56
combinerReturnType = void.class;
57
} else {
58
combinerReturnType = Helper.RNG.nextBoolean() ? void.class : mtTarget.parameterType(0);
59
}
60
data.put("combinerReturnType", combinerReturnType);
61
return data;
62
}
63
64
@Override
65
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
66
MethodType mtTarget = (MethodType) data.get("mtTarget");
67
Class<?> combinerReturnType = (Class) data.get("combinerReturnType");
68
int modifierMHArgNum = (int) data.get("modifierMHArgNum");
69
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
70
mtTarget.parameterList(), kind);
71
Class<?> rType = mtTarget.returnType();
72
int combListStart = (combinerReturnType == void.class) ? 0 : 1;
73
if (modifierMHArgNum < combListStart) {
74
modifierMHArgNum = combListStart;
75
}
76
MethodHandle combiner = TestMethods.methodHandleGenerator(combinerReturnType,
77
mtTarget.parameterList().subList(combListStart,
78
modifierMHArgNum), kind);
79
return MethodHandles.foldArguments(target, combiner);
80
}
81
},
82
DROP_ARGUMENTS("dropArguments") {
83
@Override
84
public Map<String, Object> getTestCaseData() {
85
Map<String, Object> data = new HashMap<>();
86
int desiredArity = Helper.RNG.nextInt(super.maxArity);
87
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
88
data.put("mtTarget", mtTarget);
89
// Arity after reducing because of long and double take 2 slots.
90
int realArity = mtTarget.parameterCount();
91
int dropArgsPos = Helper.RNG.nextInt(realArity + 1);
92
data.put("dropArgsPos", dropArgsPos);
93
MethodType mtDropArgs = TestMethods.randomMethodTypeGenerator(
94
Helper.RNG.nextInt(super.maxArity - realArity));
95
data.put("mtDropArgs", mtDropArgs);
96
return data;
97
}
98
99
@Override
100
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
101
MethodType mtTarget = (MethodType) data.get("mtTarget");
102
MethodType mtDropArgs = (MethodType) data.get("mtDropArgs");
103
int dropArgsPos = (int) data.get("dropArgsPos");
104
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
105
mtTarget.parameterList(), kind);
106
int mtTgtSlotsCount = TestMethods.argSlotsCount(mtTarget);
107
int mtDASlotsCount = TestMethods.argSlotsCount(mtDropArgs);
108
List<Class<?>> fakeParList;
109
if (mtTgtSlotsCount + mtDASlotsCount > super.maxArity - 1) {
110
fakeParList = TestMethods.reduceArgListToSlotsCount(mtDropArgs.parameterList(),
111
super.maxArity - mtTgtSlotsCount - 1);
112
} else {
113
fakeParList = mtDropArgs.parameterList();
114
}
115
return MethodHandles.dropArguments(target, dropArgsPos, fakeParList);
116
}
117
},
118
EXPLICIT_CAST_ARGUMENTS("explicitCastArguments", Helper.MAX_ARITY / 2) {
119
@Override
120
public Map<String, Object> getTestCaseData() {
121
Map<String, Object> data = new HashMap<>();
122
int desiredArity = Helper.RNG.nextInt(super.maxArity);
123
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
124
data.put("mtTarget", mtTarget);
125
// Arity after reducing because of long and double take 2 slots.
126
int realArity = mtTarget.parameterCount();
127
MethodType mtExcplCastArgs = TestMethods.randomMethodTypeGenerator(realArity);
128
if (mtTarget.returnType() == void.class) {
129
mtExcplCastArgs = MethodType.methodType(void.class,
130
mtExcplCastArgs.parameterArray());
131
}
132
if (mtExcplCastArgs.returnType() == void.class) {
133
mtExcplCastArgs = MethodType.methodType(mtTarget.returnType(),
134
mtExcplCastArgs.parameterArray());
135
}
136
data.put("mtExcplCastArgs", mtExcplCastArgs);
137
return data;
138
}
139
140
@Override
141
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
142
MethodType mtTarget = (MethodType) data.get("mtTarget");
143
MethodType mtExcplCastArgs = (MethodType) data.get("mtExcplCastArgs");
144
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
145
mtTarget.parameterList(), kind);
146
return MethodHandles.explicitCastArguments(target, mtExcplCastArgs);
147
}
148
},
149
FILTER_ARGUMENTS("filterArguments", Helper.MAX_ARITY / 2) {
150
@Override
151
public Map<String, Object> getTestCaseData() {
152
Map<String, Object> data = new HashMap<>();
153
int desiredArity = Helper.RNG.nextInt(super.maxArity);
154
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
155
data.put("mtTarget", mtTarget);
156
// Arity after reducing because of long and double take 2 slots.
157
int realArity = mtTarget.parameterCount();
158
int filterArgsPos = Helper.RNG.nextInt(realArity + 1);
159
data.put("filterArgsPos", filterArgsPos);
160
int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos);
161
data.put("filtersArgsArrayLength", filtersArgsArrayLength);
162
MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength);
163
data.put("mtFilter", mtFilter);
164
return data;
165
}
166
167
@Override
168
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
169
MethodType mtTarget = (MethodType) data.get("mtTarget");
170
MethodType mtFilter = (MethodType) data.get("mtFilter");
171
int filterArgsPos = (int) data.get("filterArgsPos");
172
int filtersArgsArrayLength = (int) data.get("filtersArgsArrayLength");
173
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
174
mtTarget.parameterList(), kind);
175
MethodHandle[] filters = new MethodHandle[filtersArgsArrayLength];
176
for (int i = 0; i < filtersArgsArrayLength; i++) {
177
filters[i] = TestMethods.filterGenerator(mtFilter.parameterType(i),
178
mtTarget.parameterType(filterArgsPos + i), kind);
179
}
180
return MethodHandles.filterArguments(target, filterArgsPos, filters);
181
}
182
},
183
FILTER_RETURN_VALUE("filterReturnValue") {
184
@Override
185
public Map<String, Object> getTestCaseData() {
186
Map<String, Object> data = new HashMap<>();
187
int desiredArity = Helper.RNG.nextInt(super.maxArity);
188
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
189
data.put("mtTarget", mtTarget);
190
// Arity after reducing because of long and double take 2 slots.
191
int realArity = mtTarget.parameterCount();
192
int filterArgsPos = Helper.RNG.nextInt(realArity + 1);
193
int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos);
194
MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength);
195
data.put("mtFilter", mtFilter);
196
return data;
197
}
198
199
@Override
200
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
201
MethodType mtTarget = (MethodType) data.get("mtTarget");
202
MethodType mtFilter = (MethodType) data.get("mtFilter");
203
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
204
mtTarget.parameterList(), kind);
205
MethodHandle filter = TestMethods.filterGenerator(mtTarget.returnType(),
206
mtFilter.returnType(), kind);
207
return MethodHandles.filterReturnValue(target, filter);
208
}
209
},
210
INSERT_ARGUMENTS("insertArguments", Helper.MAX_ARITY - 3) {
211
@Override
212
public Map<String, Object> getTestCaseData() {
213
Map<String, Object> data = new HashMap<>();
214
int desiredArity = Helper.RNG.nextInt(super.maxArity);
215
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
216
data.put("mtTarget", mtTarget);
217
// Arity after reducing because of long and double take 2 slots.
218
int realArity = mtTarget.parameterCount();
219
int insertArgsPos = Helper.RNG.nextInt(realArity + 1);
220
data.put("insertArgsPos", insertArgsPos);
221
int insertArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - insertArgsPos);
222
MethodType mtInsertArgs = MethodType.methodType(void.class, mtTarget.parameterList()
223
.subList(insertArgsPos, insertArgsPos + insertArgsArrayLength));
224
data.put("mtInsertArgs", mtInsertArgs);
225
return data;
226
}
227
228
@Override
229
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
230
MethodType mtTarget = (MethodType) data.get("mtTarget");
231
MethodType mtInsertArgs = (MethodType) data.get("mtInsertArgs");
232
int insertArgsPos = (int) data.get("insertArgsPos");
233
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
234
mtTarget.parameterList(), kind);
235
Object[] insertList = Helper.randomArgs(mtInsertArgs.parameterList());
236
return MethodHandles.insertArguments(target, insertArgsPos, insertList);
237
}
238
},
239
PERMUTE_ARGUMENTS("permuteArguments", Helper.MAX_ARITY / 2) {
240
@Override
241
public Map<String, Object> getTestCaseData() {
242
Map<String, Object> data = new HashMap<>();
243
int desiredArity = Helper.RNG.nextInt(super.maxArity);
244
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
245
// Arity after reducing because of long and double take 2 slots.
246
int realArity = mtTarget.parameterCount();
247
int[] permuteArgsReorderArray = new int[realArity];
248
int mtPermuteArgsNum = Helper.RNG.nextInt(Helper.MAX_ARITY);
249
mtPermuteArgsNum = mtPermuteArgsNum == 0 ? 1 : mtPermuteArgsNum;
250
MethodType mtPermuteArgs = TestMethods.randomMethodTypeGenerator(mtPermuteArgsNum);
251
mtTarget = mtTarget.changeReturnType(mtPermuteArgs.returnType());
252
for (int i = 0; i < realArity; i++) {
253
int mtPermuteArgsParNum = Helper.RNG.nextInt(mtPermuteArgs.parameterCount());
254
permuteArgsReorderArray[i] = mtPermuteArgsParNum;
255
mtTarget = mtTarget.changeParameterType(
256
i, mtPermuteArgs.parameterType(mtPermuteArgsParNum));
257
}
258
data.put("mtTarget", mtTarget);
259
data.put("permuteArgsReorderArray", permuteArgsReorderArray);
260
data.put("mtPermuteArgs", mtPermuteArgs);
261
return data;
262
}
263
264
@Override
265
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
266
MethodType mtTarget = (MethodType) data.get("mtTarget");
267
MethodType mtPermuteArgs = (MethodType) data.get("mtPermuteArgs");
268
int[] permuteArgsReorderArray = (int[]) data.get("permuteArgsReorderArray");
269
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
270
mtTarget.parameterList(), kind);
271
return MethodHandles.permuteArguments(target, mtPermuteArgs, permuteArgsReorderArray);
272
}
273
},
274
THROW_EXCEPTION("throwException") {
275
@Override
276
public Map<String, Object> getTestCaseData() {
277
Map<String, Object> data = new HashMap<>();
278
int desiredArity = Helper.RNG.nextInt(super.maxArity);
279
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
280
data.put("mtTarget", mtTarget);
281
return data;
282
}
283
284
@Override
285
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
286
MethodType mtTarget = (MethodType) data.get("mtTarget");
287
Class<?> rType = mtTarget.returnType();
288
return MethodHandles.throwException(rType, Exception.class
289
);
290
}
291
},
292
GUARD_WITH_TEST("guardWithTest") {
293
@Override
294
public Map<String, Object> getTestCaseData() {
295
Map<String, Object> data = new HashMap<>();
296
int desiredArity = Helper.RNG.nextInt(super.maxArity);
297
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
298
data.put("mtTarget", mtTarget);
299
// Arity after reducing because of long and double take 2 slots.
300
int realArity = mtTarget.parameterCount();
301
int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
302
data.put("modifierMHArgNum", modifierMHArgNum);
303
return data;
304
}
305
306
@Override
307
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
308
MethodType mtTarget = (MethodType) data.get("mtTarget");
309
int modifierMHArgNum = (int) data.get("modifierMHArgNum");
310
TestMethods.Kind targetKind;
311
TestMethods.Kind fallbackKind;
312
if (kind.equals(TestMethods.Kind.ONE)) {
313
targetKind = TestMethods.Kind.ONE;
314
fallbackKind = TestMethods.Kind.TWO;
315
} else {
316
targetKind = TestMethods.Kind.TWO;
317
fallbackKind = TestMethods.Kind.ONE;
318
}
319
MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
320
mtTarget.parameterList(), targetKind);
321
MethodHandle fallback = TestMethods.methodHandleGenerator(mtTarget.returnType(),
322
mtTarget.parameterList(), fallbackKind);
323
MethodHandle test = TestMethods.methodHandleGenerator(boolean.class,
324
mtTarget.parameterList().subList(0, modifierMHArgNum), kind);
325
return MethodHandles.guardWithTest(test, target, fallback);
326
}
327
},
328
CATCH_EXCEPTION("catchException") {
329
@Override
330
public Map<String, Object> getTestCaseData() {
331
Map<String, Object> data = new HashMap<>();
332
int desiredArity = Helper.RNG.nextInt(super.maxArity);
333
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
334
data.put("mtTarget", mtTarget);
335
// Arity after reducing because of long and double take 2 slots.
336
int realArity = mtTarget.parameterCount();
337
int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
338
data.put("modifierMHArgNum", modifierMHArgNum);
339
return data;
340
}
341
342
@Override
343
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
344
MethodType mtTarget = (MethodType) data.get("mtTarget");
345
int modifierMHArgNum = (int) data.get("modifierMHArgNum");
346
MethodHandle target;
347
if (kind.equals(TestMethods.Kind.ONE)) {
348
target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
349
mtTarget.parameterList(), TestMethods.Kind.ONE);
350
} else {
351
target = TestMethods.methodHandleGenerator(mtTarget.returnType(),
352
mtTarget.parameterList(), TestMethods.Kind.EXCEPT);
353
}
354
List<Class<?>> handlerParamList = new ArrayList<>(mtTarget.parameterCount() + 1);
355
handlerParamList.add(Exception.class);
356
handlerParamList.addAll(mtTarget.parameterList().subList(0, modifierMHArgNum));
357
MethodHandle handler = TestMethods.methodHandleGenerator(
358
mtTarget.returnType(), handlerParamList, TestMethods.Kind.TWO);
359
return MethodHandles.catchException(target, Exception.class, handler);
360
}
361
},
362
INVOKER("invoker", Helper.MAX_ARITY - 1) {
363
@Override
364
public Map<String, Object> getTestCaseData() {
365
Map<String, Object> data = new HashMap<>();
366
int desiredArity = Helper.RNG.nextInt(super.maxArity);
367
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
368
data.put("mtTarget", mtTarget);
369
return data;
370
}
371
372
@Override
373
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
374
MethodType mtTarget = (MethodType) data.get("mtTarget");
375
return MethodHandles.invoker(mtTarget);
376
}
377
},
378
EXACT_INVOKER("exactInvoker", Helper.MAX_ARITY - 1) {
379
@Override
380
public Map<String, Object> getTestCaseData() {
381
Map<String, Object> data = new HashMap<>();
382
int desiredArity = Helper.RNG.nextInt(super.maxArity);
383
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
384
data.put("mtTarget", mtTarget);
385
return data;
386
}
387
388
@Override
389
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
390
MethodType mtTarget = (MethodType) data.get("mtTarget");
391
return MethodHandles.exactInvoker(mtTarget);
392
}
393
},
394
SPREAD_INVOKER("spreadInvoker", Helper.MAX_ARITY - 1) {
395
@Override
396
public Map<String, Object> getTestCaseData() {
397
Map<String, Object> data = new HashMap<>();
398
int desiredArity = Helper.RNG.nextInt(super.maxArity);
399
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
400
data.put("mtTarget", mtTarget);
401
// Arity after reducing because of long and double take 2 slots.
402
int realArity = mtTarget.parameterCount();
403
int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1);
404
data.put("modifierMHArgNum", modifierMHArgNum);
405
return data;
406
}
407
408
@Override
409
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
410
MethodType mtTarget = (MethodType) data.get("mtTarget");
411
int modifierMHArgNum = (int) data.get("modifierMHArgNum");
412
return MethodHandles.spreadInvoker(mtTarget, modifierMHArgNum);
413
}
414
},
415
ARRAY_ELEMENT_GETTER("arrayElementGetter") {
416
@Override
417
public Map<String, Object> getTestCaseData() {
418
Map<String, Object> data = new HashMap<>();
419
int desiredArity = Helper.RNG.nextInt(super.maxArity);
420
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
421
data.put("mtTarget", mtTarget);
422
return data;
423
}
424
425
@Override
426
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
427
MethodType mtTarget = (MethodType) data.get("mtTarget");
428
Class<?> rType = mtTarget.returnType();
429
if (rType == void.class) {
430
rType = Object.class;
431
}
432
return MethodHandles.arrayElementGetter(Array.newInstance(rType, 2).getClass());
433
}
434
},
435
ARRAY_ELEMENT_SETTER("arrayElementSetter") {
436
@Override
437
public Map<String, Object> getTestCaseData() {
438
Map<String, Object> data = new HashMap<>();
439
int desiredArity = Helper.RNG.nextInt(super.maxArity);
440
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
441
data.put("mtTarget", mtTarget);
442
return data;
443
}
444
445
@Override
446
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
447
MethodType mtTarget = (MethodType) data.get("mtTarget");
448
Class<?> rType = mtTarget.returnType();
449
if (rType == void.class) {
450
rType = Object.class;
451
}
452
return MethodHandles.arrayElementSetter(Array.newInstance(rType, 2).getClass());
453
}
454
},
455
CONSTANT("constant") {
456
@Override
457
public Map<String, Object> getTestCaseData() {
458
Map<String, Object> data = new HashMap<>();
459
int desiredArity = Helper.RNG.nextInt(super.maxArity);
460
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
461
data.put("mtTarget", mtTarget);
462
return data;
463
}
464
465
@Override
466
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
467
MethodType mtTarget = (MethodType) data.get("mtTarget");
468
Class<?> rType = mtTarget.returnType();
469
if (rType == void.class) {
470
rType = Object.class;
471
}
472
if (rType.equals(boolean.class)) {
473
// There should be the same return values because for default values there are special "zero" forms
474
return MethodHandles.constant(rType, true);
475
} else {
476
return MethodHandles.constant(rType, kind.getValue(rType));
477
}
478
}
479
},
480
IDENTITY("identity") {
481
@Override
482
public Map<String, Object> getTestCaseData() {
483
Map<String, Object> data = new HashMap<>();
484
int desiredArity = Helper.RNG.nextInt(super.maxArity);
485
MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity);
486
data.put("mtTarget", mtTarget);
487
return data;
488
}
489
490
@Override
491
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) {
492
MethodType mtTarget = (MethodType) data.get("mtTarget");
493
Class<?> rType = mtTarget.returnType();
494
if (rType == void.class) {
495
rType = Object.class;
496
}
497
return MethodHandles.identity(rType);
498
}
499
};
500
501
/**
502
* Test method's name.
503
*/
504
public final String name;
505
506
private final int maxArity;
507
508
private TestMethods(String name, int maxArity) {
509
this.name = name;
510
this.maxArity = maxArity;
511
}
512
513
private TestMethods(String name) {
514
this(name, Helper.MAX_ARITY);
515
}
516
517
protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
518
throw new UnsupportedOperationException("TESTBUG: getMH method is not implemented for test method " + this);
519
}
520
521
/**
522
* Creates an adapter method handle depending on a test method from
523
* MethodHandles class. Adapter is what is returned by the test method. This
524
* method is able to create two kinds of adapters, their type will be the
525
* same, but return values are different.
526
*
527
* @param data a Map containing data to create a method handle, can be
528
* obtained by {@link #getTestCaseData} method
529
* @param kind defines whether adapter ONE or adapter TWO will be
530
* initialized. Should be equal to TestMethods.Kind.ONE or
531
* TestMethods.Kind.TWO
532
* @return Method handle adapter that behaves according to
533
* TestMethods.Kind.ONE or TestMethods.Kind.TWO
534
* @throws java.lang.NoSuchMethodException
535
* @throws java.lang.IllegalAccessException
536
*/
537
public MethodHandle getTestCaseMH(Map<String, Object> data, TestMethods.Kind kind)
538
throws NoSuchMethodException, IllegalAccessException {
539
if (data == null) {
540
throw new Error(String.format("TESTBUG: Data for test method %s is not prepared",
541
this.name));
542
}
543
if (!kind.equals(TestMethods.Kind.ONE) && !kind.equals(TestMethods.Kind.TWO)) {
544
throw new IllegalArgumentException("TESTBUG: Wrong \"kind\" (" + kind
545
+ ") arg to getTestCaseMH function."
546
+ " Should be Kind.ONE or Kind.TWO");
547
}
548
return getMH(data, kind);
549
}
550
551
/**
552
* Returns a data Map needed for {@link #getTestCaseMH} method.
553
*
554
* @return data Map needed for {@link #getTestCaseMH} method
555
*/
556
public Map<String, Object> getTestCaseData() {
557
throw new UnsupportedOperationException(
558
"TESTBUG: getTestCaseData method is not implemented for test method " + this);
559
}
560
561
/**
562
* Enumeration used in methodHandleGenerator to define whether a MH returned
563
* by this method returns "2" in different type representations, "4", or
564
* throw an Exception.
565
*/
566
public static enum Kind {
567
568
ONE(2),
569
TWO(4),
570
EXCEPT(0);
571
572
private final int value;
573
574
private Object getValue(Class<?> cl) {
575
return Helper.castToWrapper(value, cl);
576
}
577
578
private MethodHandle getBasicMH(Class<?> rType) throws NoSuchMethodException, IllegalAccessException {
579
MethodHandle result = null;
580
switch (this) {
581
case ONE:
582
case TWO:
583
if (rType.equals(void.class)) {
584
result = MethodHandles.lookup().findVirtual(Kind.class, "returnVoid", MethodType.methodType(void.class));
585
result = MethodHandles.insertArguments(result, 0, this);
586
} else {
587
result = MethodHandles.constant(rType, getValue(rType));
588
}
589
break;
590
case EXCEPT:
591
result = MethodHandles.throwException(rType, Exception.class);
592
result = MethodHandles.insertArguments(result, 0, new Exception());
593
break;
594
}
595
return result;
596
}
597
598
private void returnVoid() {
599
}
600
601
private Kind(int value) {
602
this.value = value;
603
}
604
}
605
606
/**
607
* Routine used to obtain a randomly generated method type.
608
*
609
* @param arity Arity of returned method type.
610
* @return MethodType generated randomly.
611
*/
612
private static MethodType randomMethodTypeGenerator(int arity) {
613
return Helper.randomMethodTypeGenerator(arity);
614
}
615
616
/**
617
* Routine used to obtain a method handles of a given type an kind (return
618
* value).
619
*
620
* @param returnType Type of MH return value.
621
* @param argTypes Types of MH args.
622
* @param kind Defines whether the obtained MH returns "1" or "2".
623
* @return Method handle of the given type.
624
* @throws NoSuchMethodException
625
* @throws IllegalAccessException
626
*/
627
private static MethodHandle methodHandleGenerator(Class<?> returnType,
628
List<Class<?>> argTypes, TestMethods.Kind kind)
629
throws NoSuchMethodException, IllegalAccessException {
630
MethodHandle result;
631
result = kind.getBasicMH(returnType);
632
return Helper.addTrailingArgs(result, argTypes.size(), argTypes);
633
}
634
635
/**
636
* Routine that generates filter method handles to test
637
* MethodHandles.filterArguments method.
638
*
639
* @param inputType Filter's argument type.
640
* @param returnType Filter's return type.
641
* @param kind Filter's return value definer.
642
* @return A filter method handle, that takes one argument.
643
* @throws NoSuchMethodException
644
* @throws IllegalAccessException
645
*/
646
private static MethodHandle filterGenerator(Class<?> inputType, Class<?> returnType,
647
TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
648
MethodHandle tmpMH = kind.getBasicMH(returnType);
649
if (inputType.equals(void.class)) {
650
return tmpMH;
651
}
652
ArrayList<Class<?>> inputTypeList = new ArrayList<>(1);
653
inputTypeList.add(inputType);
654
return Helper.addTrailingArgs(tmpMH, 1, inputTypeList);
655
}
656
657
private static int argSlotsCount(MethodType mt) {
658
int result = 0;
659
for (Class cl : mt.parameterArray()) {
660
if (cl.equals(long.class) || cl.equals(double.class)) {
661
result += 2;
662
} else {
663
result++;
664
}
665
}
666
return result;
667
}
668
669
private static List<Class<?>> reduceArgListToSlotsCount(List<Class<?>> list,
670
int desiredSlotCount) {
671
List<Class<?>> result = new ArrayList<>(desiredSlotCount);
672
int count = 0;
673
for (Class<?> cl : list) {
674
if (count >= desiredSlotCount) {
675
break;
676
}
677
if (cl.equals(long.class) || cl.equals(double.class)) {
678
count += 2;
679
} else {
680
count++;
681
}
682
result.add(cl);
683
}
684
return result;
685
}
686
}
687
688