/* * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
// Set this true during development if you want to fast-forward to // a particular new, non-working test. Tests which are known to // work (or have recently worked) test this flag and return on true. staticfinalboolean CAN_SKIP_WORKING;
// Set 'true' to do about 15x fewer tests, especially those redundant with RicochetTest. // This might be useful with -Xcomp stress tests that compile all method handles. staticboolean CAN_TEST_LIGHTLY = Boolean.getBoolean(THIS_CLASS.getName()+".CAN_TEST_LIGHTLY");
staticfinalint MAX_ARG_INCREASE = 3;
String testName; staticint allPosTests, allNegTests; int posTests, negTests;
@SuppressWarnings("cast") // primitive cast to (long) is part of the pattern static Object castToWrapperOrNull(long value, Class<?> dst) { if (dst == int.class || dst == Integer.class) return (int)(value); if (dst == long.class || dst == Long.class) return (long)(value); if (dst == char.class || dst == Character.class) return (char)(value); if (dst == short.class || dst == Short.class) return (short)(value); if (dst == float.class || dst == Float.class) return (float)(value); if (dst == double.class || dst == Double.class) return (double)(value); if (dst == byte.class || dst == Byte.class) return (byte)(value); if (dst == boolean.class || dst == boolean.class) return ((value % 29) & 1) == 0; returnnull;
}
staticfinalint ONE_MILLION = (1000*1000), // first int value
TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits
INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit; staticlong nextArgVal;
staticlong nextArg(boolean moreBits) { long val = nextArgVal++; long sign = -(val & 1); // alternate signs
val >>= 1; if (moreBits) // Guarantee some bits in the high word. // In any case keep the decimal representation simple-looking, // with lots of zeroes, so as not to make the printed decimal // strings unnecessarily noisy.
val += (val % ONE_MILLION) * TEN_BILLION; return val ^ sign;
}
staticint nextArg() { // Produce a 32-bit result something like ONE_MILLION+(smallint). // Example: 1_000_042. return (int) nextArg(false);
}
staticlong nextArg(Class<?> kind) { if (kind == long.class || kind == Long.class ||
kind == double.class || kind == Double.class) // produce a 64-bit result something like // ((TEN_BILLION+1) * (ONE_MILLION+(smallint))) // Example: 10_000_420_001_000_042. return nextArg(true); return (long) nextArg();
}
static Object randomArg(Class<?> param) {
Object wrap = castToWrapperOrNull(nextArg(param), param); if (wrap != null) { return wrap;
} //import sun.invoke.util.Wrapper; //Wrapper wrap = Wrapper.forBasicType(dst); //if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst)) // wrap = Wrapper.forWrapperType(dst); // if (wrap != Wrapper.OBJECT) // return wrap.wrap(nextArg++); if (param.isInterface()) { for (Class<?> c : param.getClasses()) { if (param.isAssignableFrom(c) && !c.isInterface())
{ param = c; break; }
}
} if (param.isArray()) { Class<?> ctype = param.getComponentType();
Object arg = Array.newInstance(ctype, 2);
Array.set(arg, 0, randomArg(ctype)); return arg;
} if (param.isInterface() && param.isAssignableFrom(List.class)) return Arrays.asList("#"+nextArg()); if (param.isInterface() || param.isAssignableFrom(String.class)) return"#"+nextArg(); else try { return param.newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
} returnnull; // random class not Object, String, Integer, etc.
}
static Object[] randomArgs(Class<?>... params) {
Object[] args = new Object[params.length]; for (int i = 0; i < args.length; i++)
args[i] = randomArg(params[i]); return args;
}
static Object[] randomArgs(int nargs, Class<?> param) {
Object[] args = new Object[nargs]; for (int i = 0; i < args.length; i++)
args[i] = randomArg(param); return args;
}
@SafeVarargs @SuppressWarnings("varargs") static <T, E extends T> T[] array(Class<T[]> atype, E... a) { return Arrays.copyOf(a, a.length, atype);
}
@SafeVarargs @SuppressWarnings("varargs") static <T> T[] cat(T[] a, T... b) { int alen = a.length, blen = b.length; if (blen == 0) return a;
T[] c = Arrays.copyOf(a, alen + blen);
System.arraycopy(b, 0, c, alen, blen); return c;
}
static Integer[] boxAll(int... vx) {
Integer[] res = new Integer[vx.length]; for (int i = 0; i < res.length; i++) {
res[i] = vx[i];
} return res;
}
static Object getClasses(Object x) { if (x == null) return x; if (x instanceof String) return x; // keep the name if (x instanceof List) { // recursively report classes of the list elements
Object[] xa = ((List)x).toArray(); for (int i = 0; i < xa.length; i++)
xa[i] = getClasses(xa[i]); return Arrays.asList(xa);
} return x.getClass().getSimpleName();
}
/** Variation of varargsList, but with the given rtype. */ static MethodHandle varargsList(int arity, Class<?> rtype) {
MethodHandle list = varargsList(arity);
MethodType listType = list.type().changeReturnType(rtype); if (List.class.isAssignableFrom(rtype) || rtype == void.class || rtype == Object.class) { // OK
} elseif (rtype.isAssignableFrom(String.class)) { if (LIST_TO_STRING == null) try {
LIST_TO_STRING = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToString",
MethodType.methodType(String.class, List.class));
} catch (NoSuchMethodException | IllegalAccessException ex) { thrownew RuntimeException(ex); }
list = MethodHandles.filterReturnValue(list, LIST_TO_STRING);
} elseif (rtype.isPrimitive()) { if (LIST_TO_INT == null) try {
LIST_TO_INT = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToInt",
MethodType.methodType(int.class, List.class));
} catch (NoSuchMethodException | IllegalAccessException ex) { thrownew RuntimeException(ex); }
list = MethodHandles.filterReturnValue(list, LIST_TO_INT);
list = MethodHandles.explicitCastArguments(list, listType);
} else { thrownew RuntimeException("varargsList: "+rtype);
} return list.asType(listType);
}
/** Variation of varargsList, but with the given ptypes and rtype. */ static MethodHandle varargsList(List<Class<?>> ptypes, Class<?> rtype) {
MethodHandle list = varargsList(ptypes.size(), rtype); return list.asType(MethodType.methodType(rtype, ptypes));
}
static MethodHandle changeArgTypes(MethodHandle target, int beg, int end, Class<?> argType) {
MethodType targetType = target.type();
end = Math.min(end, targetType.parameterCount());
ArrayList<Class<?>> argTypes = new ArrayList<>(targetType.parameterList());
Collections.fill(argTypes.subList(beg, end), argType);
MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); return target.asType(ttype2);
}
static MethodHandle addTrailingArgs(MethodHandle target, int nargs, Class<?> argClass) { int targetLen = target.type().parameterCount(); int extra = (nargs - targetLen); if (extra <= 0) return target;
List<Class<?>> fakeArgs = Collections.<Class<?>>nCopies(extra, argClass); return MethodHandles.dropArguments(target, targetLen, fakeArgs);
}
// This lookup is good for all members in and under MethodHandlesTest. staticfinal Lookup PRIVATE = MethodHandles.lookup(); // This lookup is good for package-private members but not private ones. staticfinal Lookup PACKAGE = PackageSibling.lookup(); // This lookup is good for public members and protected members of PubExample staticfinal Lookup SUBCLASS = RemoteExample.lookup(); // This lookup is good only for public members in exported packages. staticfinal Lookup PUBLIC = MethodHandles.publicLookup();
// Subject methods... staticclass Example implements IntExample { final String name; public Example() { name = "Example#"+nextArg(); } protected Example(String name) { this.name = name; }
@SuppressWarnings("LeakingThisInConstructor") protected Example(int x) { this(); called("protected ", this, x); } //Example(Void x) { does not exist; lookup elicts NoSuchMethodException }
@Override public String toString() { return name; }
privatestatic Object[] mapTestCase(int testMode, Object[] c) { // non-final fields (2-element) and final fields (3-element) if not TEST_SETTER if (c.length == 2 || (testMode & TEST_SETTER) == 0) return c;
// final fields (3-element)
assertTrue((testMode & TEST_SETTER) != 0 && c[0] instanceof Field && c[2] == Error.class); if ((testMode & TEST_UNREFLECT) == 0) returnnew Object[]{ c[0], c[2]}; // negative test case; can't set on final fields
// unreflectSetter grants write access on instance final field if accessible flag is true // hence promote the negative test case to positive test case
Field f = (Field) c[0]; int mods = f.getModifiers(); if (!Modifier.isFinal(mods) || (!Modifier.isStatic(mods) && f.isAccessible())) { // positive test case returnnew Object[]{ c[0], c[1] };
} else { // otherwise, negative test case returnnew Object[]{ c[0], c[2]};
}
}
}
static Object targetIfEquals(Object x, Object y, Object z) {
assertEquals(x, y); return called("targetIfEquals", x, y, z);
}
static Object fallbackIfNotEquals(Object x, Object y, Object z) {
assertFalse(x.toString(), x.equals(y)); return called("fallbackIfNotEquals", x, y, z);
}
staticboolean loopIntPred(int a) { if (verbosity >= 5) {
System.out.println("int pred " + a + " -> " + (a < 7));
} return a < 7;
}
staticboolean loopDoublePred(int a, double b) { if (verbosity >= 5) {
System.out.println("double pred (a=" + a + ") " + b + " -> " + (b > 0.5));
} return b > 0.5;
}
staticboolean loopStringPred(int a, double b, String c) { if (verbosity >= 5) {
System.out.println("String pred (a=" + a + ",b=" + b + ") " + c + " -> " + (c.length() <= 9));
} return c.length() <= 9;
}
staticint loopIntStep(int a) { if (verbosity >= 5) {
System.out.println("int step " + a + " -> " + (a + 1));
} return a + 1;
}
staticdouble loopDoubleStep(int a, double b) { if (verbosity >= 5) {
System.out.println("double step (a=" + a + ") " + b + " -> " + (b / 2.0));
} return b / 2.0;
}
static String loopStringStep(int a, double b, String c) { if (verbosity >= 5) {
System.out.println("String step (a=" + a + ",b=" + b + ") " + c + " -> " + (c + a));
} return c + a;
}
staticvoid vtarget(String[] a) { // naught, akin to identity
}
staticvoid vtargetThrow(String[] a) throws Exception { thrownew Exception("thrown");
}
staticvoid vcleanupPassThrough(Throwable t, String[] a) {
assertNull(t); // naught, akin to identity
}
static MethodHandle[] makeArrays() {
ArrayList<MethodHandle> arrays = new ArrayList<>();
MethodHandles.Lookup lookup = IMPL_LOOKUP; for (;;) { int nargs = arrays.size();
MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
String name = "array";
MethodHandle array = null; try {
array = lookup.findStatic(ValueConversions.class, name, type);
} catch (ReflectiveOperationException ex) { // break from loop!
} if (array == null) break;
arrays.add(array);
}
assertTrue(arrays.size() == 11); // current number of methods return arrays.toArray(new MethodHandle[0]);
}
staticfinal MethodHandle[] ARRAYS = makeArrays();
/** Return a method handle that takes the indicated number of Object * arguments and returns an Object array of them, as if for varargs.
*/ publicstatic MethodHandle varargsArray(int nargs) { if (nargs < ARRAYS.length) return ARRAYS[nargs]; return MethodHandles.identity(Object[].class).asCollector(Object[].class, nargs);
}
/** Return a method handle that takes the indicated number of Object * arguments and returns List.
*/ publicstatic MethodHandle varargsList(int nargs) { if (nargs < LISTS.length) return LISTS[nargs]; return AS_LIST.asCollector(Object[].class, nargs);
}
} // This guy tests access from outside the same package member, but inside // the package itself. class PackageSibling { static Lookup lookup() { return MethodHandles.lookup();
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.