test/java/lang/invoke/LFCaching/TestMethods.java

Print this page




  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(Helper.MAX_ARITY);
  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(Helper.MAX_ARITY);
  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(Helper.MAX_ARITY - 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 > Helper.MAX_ARITY - 1) {
 110                         fakeParList = TestMethods.reduceArgListToSlotsCount(mtDropArgs.parameterList(),
 111                                 Helper.MAX_ARITY - mtTgtSlotsCount - 1);
 112                     } else {
 113                         fakeParList = mtDropArgs.parameterList();
 114                     }
 115                     return MethodHandles.dropArguments(target, dropArgsPos, fakeParList);
 116                 }
 117             },
 118     EXPLICIT_CAST_ARGUMENTS("explicitCastArguments") {
 119                 @Override
 120                 public Map<String, Object> getTestCaseData() {
 121                     Map<String, Object> data = new HashMap<>();
 122                     int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2);
 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") {
 150                 @Override
 151                 public Map<String, Object> getTestCaseData() {
 152                     Map<String, Object> data = new HashMap<>();
 153                     int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2);
 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(Helper.MAX_ARITY);
 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") {
 211                 @Override
 212                 public Map<String, Object> getTestCaseData() {
 213                     Map<String, Object> data = new HashMap<>();
 214                     int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
 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") {
 240                 @Override
 241                 public Map<String, Object> getTestCaseData() {
 242                     Map<String, Object> data = new HashMap<>();
 243                     int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2);
 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 mtParmuteArgsNum = Helper.RNG.nextInt(Helper.MAX_ARITY);
 249                     mtParmuteArgsNum = mtParmuteArgsNum == 0 ? 1 : mtParmuteArgsNum;
 250                     MethodType mtPermuteArgs = TestMethods.randomMethodTypeGenerator(mtParmuteArgsNum);
 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(Helper.MAX_ARITY);
 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(Helper.MAX_ARITY);
 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(Helper.MAX_ARITY);
 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") {
 363                 @Override
 364                 public Map<String, Object> getTestCaseData() {
 365                     Map<String, Object> data = new HashMap<>();
 366                     int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
 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") {
 379                 @Override
 380                 public Map<String, Object> getTestCaseData() {
 381                     Map<String, Object> data = new HashMap<>();
 382                     int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
 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") {
 395                 @Override
 396                 public Map<String, Object> getTestCaseData() {
 397                     Map<String, Object> data = new HashMap<>();
 398                     int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY);
 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(Helper.MAX_ARITY);
 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(Helper.MAX_ARITY);
 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(Helper.MAX_ARITY);
 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(Helper.MAX_ARITY);
 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 TestMethods(String name) {


 507         this.name = name;





 508     }
 509 
 510     protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException {
 511         throw new UnsupportedOperationException("TESTBUG: getMH method is not implemented for test method " + this);
 512     }
 513 
 514     /**
 515      * Creates an adapter method handle depending on a test method from
 516      * MethodHandles class. Adapter is what is returned by the test method. This
 517      * method is able to create two kinds of adapters, their type will be the
 518      * same, but return values are different.
 519      *
 520      * @param data a Map containing data to create a method handle, can be
 521      * obtained by {@link #getTestCaseData} method
 522      * @param kind defines whether adapter ONE or adapter TWO will be
 523      * initialized. Should be equal to TestMethods.Kind.ONE or
 524      * TestMethods.Kind.TWO
 525      * @return Method handle adapter that behaves according to
 526      * TestMethods.Kind.ONE or TestMethods.Kind.TWO
 527      * @throws java.lang.NoSuchMethodException




  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") {
 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