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