1 /* 2 * Copyright (c) 2018, 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 /* @test 25 * @summary unit tests for java.lang.invoke.MethodHandles 26 * @library /lib/testlibrary /java/lang/invoke/common 27 * @compile MethodHandlesTest.java MethodHandlesAsCollectorTest.java remote/RemoteExample.java 28 * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions 29 * -XX:-VerifyDependencies 30 * -esa 31 * test.java.lang.invoke.MethodHandlesAsCollectorTest 32 */ 33 34 package test.java.lang.invoke; 35 36 import org.junit.*; 37 import test.java.lang.invoke.lib.CodeCacheOverflowProcessor; 38 39 import java.lang.invoke.MethodHandle; 40 import java.lang.invoke.MethodType; 41 import java.util.Arrays; 42 43 import static org.junit.Assert.*; 44 45 public class MethodHandlesAsCollectorTest extends MethodHandlesTest { 46 47 @Test // SLOW 48 public void testAsCollector() throws Throwable { 49 CodeCacheOverflowProcessor.runMHTest(this::testAsCollector0); 50 CodeCacheOverflowProcessor.runMHTest(this::testAsCollector1); 51 } 52 53 public void testAsCollector0() throws Throwable { 54 if (CAN_SKIP_WORKING) return; 55 startTest("asCollector"); 56 for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) { 57 if (verbosity >= 3) 58 System.out.println("asCollector "+argType); 59 for (int nargs = 0; nargs < 50; nargs++) { 60 if (CAN_TEST_LIGHTLY && nargs > 11) break; 61 for (int pos = 0; pos <= nargs; pos++) { 62 if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; 63 if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) 64 continue; 65 testAsCollector(argType, pos, nargs); 66 } 67 } 68 } 69 } 70 71 public void testAsCollector(Class<?> argType, int pos, int nargs) throws Throwable { 72 countTest(); 73 // fake up a MH with the same type as the desired adapter: 74 MethodHandle fake = varargsArray(nargs); 75 fake = changeArgTypes(fake, argType); 76 MethodType newType = fake.type(); 77 Object[] args = randomArgs(newType.parameterArray()); 78 // here is what should happen: 79 Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1); 80 collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length); 81 // here is the MH which will witness the collected argument tail: 82 MethodHandle target = varargsArray(pos+1); 83 target = changeArgTypes(target, 0, pos, argType); 84 target = changeArgTypes(target, pos, pos+1, Object[].class); 85 if (verbosity >= 3) 86 System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]"); 87 MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType); 88 Object[] returnValue = (Object[]) result.invokeWithArguments(args); 89 assertArrayEquals(collectedArgs, returnValue); 90 } 91 92 public void testAsCollector1() throws Throwable { 93 if (CAN_SKIP_WORKING) return; 94 startTest("asCollector/pos"); 95 for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) { 96 if (verbosity >= 3) 97 System.out.println("asCollector/pos "+argType); 98 for (int nargs = 0; nargs < 50; nargs++) { 99 if (CAN_TEST_LIGHTLY && nargs > 11) break; 100 for (int pos = 0; pos <= nargs; pos++) { 101 if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue; 102 if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3) 103 continue; 104 for (int coll = 1; coll < nargs - pos; ++coll) { 105 if (coll > 4 && coll != 7 && coll != 11 && coll != 20 && coll < nargs - pos - 4) continue; 106 testAsCollector(argType, pos, coll, nargs); 107 } 108 } 109 } 110 } 111 } 112 113 public void testAsCollector(Class<?> argType, int pos, int collect, int nargs) throws Throwable { 114 countTest(); 115 // fake up a MH with the same type as the desired adapter: 116 MethodHandle fake = varargsArray(nargs); 117 fake = changeArgTypes(fake, argType); 118 MethodType newType = fake.type(); 119 Object[] args = randomArgs(newType.parameterArray()); 120 // here is what should happen: 121 // new arg list has "collect" less arguments, but one extra for collected arguments array 122 int collectedLength = nargs-(collect-1); 123 Object[] collectedArgs = new Object[collectedLength]; 124 System.arraycopy(args, 0, collectedArgs, 0, pos); 125 collectedArgs[pos] = Arrays.copyOfRange(args, pos, pos+collect); 126 System.arraycopy(args, pos+collect, collectedArgs, pos+1, args.length-(pos+collect)); 127 // here is the MH which will witness the collected argument part (not tail!): 128 MethodHandle target = varargsArray(collectedLength); 129 target = changeArgTypes(target, 0, pos, argType); 130 target = changeArgTypes(target, pos, pos+1, Object[].class); 131 target = changeArgTypes(target, pos+1, collectedLength, argType); 132 if (verbosity >= 3) 133 System.out.println("collect "+collect+" from "+Arrays.asList(args)+" ["+pos+".."+(pos+collect)+"["); 134 MethodHandle result = target.asCollector(pos, Object[].class, collect).asType(newType); 135 Object[] returnValue = (Object[]) result.invokeWithArguments(args); 136 assertArrayEquals(collectedArgs, returnValue); 137 } 138 }