8252124: Restore Dynalink tests
Reviewed-by: sundar
This commit is contained in:
parent
e4eaa2377b
commit
97f8261e41
@ -295,6 +295,7 @@ jdk_other = \
|
||||
javax/smartcardio \
|
||||
javax/xml \
|
||||
-javax/xml/crypto \
|
||||
jdk/dynalink \
|
||||
jdk/internal/jline \
|
||||
com/sun/jndi \
|
||||
lib/testlibrary
|
||||
|
631
test/jdk/jdk/dynalink/BeanLinkerTest.java
Normal file
631
test/jdk/jdk/dynalink/BeanLinkerTest.java
Normal file
@ -0,0 +1,631 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import static jdk.dynalink.StandardNamespace.ELEMENT;
|
||||
import static jdk.dynalink.StandardNamespace.METHOD;
|
||||
import static jdk.dynalink.StandardNamespace.PROPERTY;
|
||||
import static jdk.dynalink.StandardOperation.CALL;
|
||||
import static jdk.dynalink.StandardOperation.GET;
|
||||
import static jdk.dynalink.StandardOperation.NEW;
|
||||
import static jdk.dynalink.StandardOperation.REMOVE;
|
||||
import static jdk.dynalink.StandardOperation.SET;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.security.AccessControlException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jdk.dynalink.CallSiteDescriptor;
|
||||
import jdk.dynalink.DynamicLinker;
|
||||
import jdk.dynalink.DynamicLinkerFactory;
|
||||
import jdk.dynalink.NamedOperation;
|
||||
import jdk.dynalink.NoSuchDynamicMethodException;
|
||||
import jdk.dynalink.Operation;
|
||||
import jdk.dynalink.beans.BeansLinker;
|
||||
import jdk.dynalink.beans.StaticClass;
|
||||
import jdk.dynalink.support.SimpleRelinkableCallSite;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @run testng/othervm/java.security.policy=untrusted.security.policy BeanLinkerTest
|
||||
*/
|
||||
public class BeanLinkerTest {
|
||||
|
||||
private DynamicLinker linker;
|
||||
private static final MethodHandles.Lookup MY_LOOKUP = MethodHandles.lookup();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@DataProvider
|
||||
private static Object[][] flags() {
|
||||
return new Object[][]{
|
||||
{Boolean.FALSE},
|
||||
{Boolean.TRUE}
|
||||
};
|
||||
}
|
||||
|
||||
// helpers to create callsite objects
|
||||
private CallSite createCallSite(final boolean publicLookup, final Operation op, final MethodType mt) {
|
||||
return linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
publicLookup ? MethodHandles.publicLookup() : MY_LOOKUP, op, mt)));
|
||||
}
|
||||
|
||||
private CallSite createCallSite(final boolean publicLookup, final Operation op, final Object name, final MethodType mt) {
|
||||
return createCallSite(publicLookup, op.named(name), mt);
|
||||
}
|
||||
|
||||
private CallSite createGetMethodCallSite(final boolean publicLookup, final String name) {
|
||||
return createCallSite(publicLookup, GET_METHOD, name, MethodType.methodType(Object.class, Object.class));
|
||||
}
|
||||
|
||||
private static final MethodHandle throwArrayIndexOutOfBounds = findThrower("throwArrayIndexOutOfBounds");
|
||||
private static final MethodHandle throwIndexOutOfBounds = findThrower("throwIndexOutOfBounds");
|
||||
|
||||
private static final Operation GET_PROPERTY = GET.withNamespace(PROPERTY);
|
||||
private static final Operation GET_ELEMENT = GET.withNamespace(ELEMENT);
|
||||
private static final Operation GET_METHOD = GET.withNamespace(METHOD);
|
||||
private static final Operation SET_ELEMENT = SET.withNamespace(ELEMENT);
|
||||
private static final Operation REMOVE_ELEMENT = REMOVE.withNamespace(ELEMENT);
|
||||
|
||||
private static MethodHandle findThrower(final String name) {
|
||||
try {
|
||||
return MethodHandles.lookup().findStatic(BeanLinkerTest.class, name,
|
||||
MethodType.methodType(Object.class, Object.class, Object.class));
|
||||
} catch (NoSuchMethodException | IllegalAccessException e) {
|
||||
Assert.fail("Unexpected exception", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object throwArrayIndexOutOfBounds(final Object receiver, final Object index) {
|
||||
throw new ArrayIndexOutOfBoundsException(String.valueOf(index));
|
||||
}
|
||||
|
||||
private static Object throwIndexOutOfBounds(final Object receiver, final Object index) {
|
||||
throw new IndexOutOfBoundsException(String.valueOf(index));
|
||||
}
|
||||
|
||||
@BeforeTest
|
||||
public void initLinker() {
|
||||
final DynamicLinkerFactory factory = new DynamicLinkerFactory();
|
||||
factory.setFallbackLinkers(new BeansLinker((req, services) -> {
|
||||
// This is a MissingMemberHandlerFactory that creates a missing
|
||||
// member handler for element getters and setters that throw an
|
||||
// ArrayIndexOutOfBoundsException when applied to an array and an
|
||||
// IndexOutOfBoundsException when applied to a list.
|
||||
|
||||
final CallSiteDescriptor desc = req.getCallSiteDescriptor();
|
||||
final Operation op = desc.getOperation();
|
||||
final Operation baseOp = NamedOperation.getBaseOperation(op);
|
||||
if (baseOp != GET_ELEMENT && baseOp != SET_ELEMENT && baseOp != REMOVE_ELEMENT) {
|
||||
// We only handle GET_ELEMENT, SET_ELEMENT and REMOVE_ELEMENT.
|
||||
return null;
|
||||
}
|
||||
|
||||
final Object receiver = req.getReceiver();
|
||||
Assert.assertNotNull(receiver);
|
||||
|
||||
final Class<?> clazz = receiver.getClass();
|
||||
final MethodHandle throwerHandle;
|
||||
if (clazz.isArray()) {
|
||||
throwerHandle = throwArrayIndexOutOfBounds;
|
||||
} else if (List.class.isAssignableFrom(clazz)) {
|
||||
throwerHandle = throwIndexOutOfBounds;
|
||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||
return null;
|
||||
} else {
|
||||
Assert.fail("Unexpected receiver type " + clazz.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
final Object name = NamedOperation.getName(op);
|
||||
final MethodHandle nameBoundHandle;
|
||||
if (name == null) {
|
||||
nameBoundHandle = throwerHandle;
|
||||
} else {
|
||||
// If the operation is for a fixed index, bind it
|
||||
nameBoundHandle = MethodHandles.insertArguments(throwerHandle, 1, name);
|
||||
}
|
||||
|
||||
final MethodType callSiteType = desc.getMethodType();
|
||||
final MethodHandle arityMatchedHandle;
|
||||
if (baseOp == SET_ELEMENT) {
|
||||
// Drop "value" parameter for a setter
|
||||
final int handleArity = nameBoundHandle.type().parameterCount();
|
||||
arityMatchedHandle = MethodHandles.dropArguments(nameBoundHandle,
|
||||
handleArity, callSiteType.parameterType(handleArity));
|
||||
} else {
|
||||
arityMatchedHandle = nameBoundHandle;
|
||||
}
|
||||
|
||||
return arityMatchedHandle.asType(callSiteType);
|
||||
}));
|
||||
this.linker = factory.createLinker();
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public void afterTest() {
|
||||
this.linker = null;
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void getPropertyTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
|
||||
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt);
|
||||
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
|
||||
Assert.assertEquals(cs.getTarget().invoke(new Date(), "class"), Date.class);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void getPropertyNegativeTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
|
||||
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt);
|
||||
Assert.assertNull(cs.getTarget().invoke(new Object(), "DOES_NOT_EXIST"));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void getPropertyTest2(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class);
|
||||
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "class", mt);
|
||||
Assert.assertEquals(cs.getTarget().invoke(new Object()), Object.class);
|
||||
Assert.assertEquals(cs.getTarget().invoke(new Date()), Date.class);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void getPropertyNegativeTest2(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class);
|
||||
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "DOES_NOT_EXIST", mt);
|
||||
|
||||
try {
|
||||
cs.getTarget().invoke(new Object());
|
||||
throw new RuntimeException("Expected NoSuchDynamicMethodException");
|
||||
} catch (final Throwable th) {
|
||||
Assert.assertTrue(th instanceof NoSuchDynamicMethodException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void getLengthPropertyTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(int.class, Object.class, String.class);
|
||||
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, mt);
|
||||
|
||||
Assert.assertEquals((int) cs.getTarget().invoke(new int[10], "length"), 10);
|
||||
Assert.assertEquals((int) cs.getTarget().invoke(new String[33], "length"), 33);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void getElementTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(int.class, Object.class, int.class);
|
||||
final CallSite cs = createCallSite(publicLookup, GET_ELEMENT, mt);
|
||||
|
||||
final int[] arr = {23, 42};
|
||||
Assert.assertEquals((int) cs.getTarget().invoke(arr, 0), 23);
|
||||
Assert.assertEquals((int) cs.getTarget().invoke(arr, 1), 42);
|
||||
try {
|
||||
final int x = (int) cs.getTarget().invoke(arr, -1);
|
||||
throw new RuntimeException("expected ArrayIndexOutOfBoundsException");
|
||||
} catch (final ArrayIndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
final int x = (int) cs.getTarget().invoke(arr, arr.length);
|
||||
throw new RuntimeException("expected ArrayIndexOutOfBoundsException");
|
||||
} catch (final ArrayIndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
final List<Integer> list = new ArrayList<>();
|
||||
list.add(23);
|
||||
list.add(430);
|
||||
list.add(-4354);
|
||||
Assert.assertEquals((int) cs.getTarget().invoke(list, 0), (int) list.get(0));
|
||||
Assert.assertEquals((int) cs.getTarget().invoke(list, 1), (int) list.get(1));
|
||||
Assert.assertEquals((int) cs.getTarget().invoke(list, 2), (int) list.get(2));
|
||||
try {
|
||||
cs.getTarget().invoke(list, -1);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
cs.getTarget().invoke(list, list.size());
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
private Object invokeWithFixedKey(boolean publicLookup, Operation op, Object name, MethodType mt, Object... args) throws Throwable {
|
||||
return createCallSite(publicLookup, op.named(name), mt).getTarget().invokeWithArguments(args);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void getElementWithFixedKeyTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(int.class, Object.class);
|
||||
|
||||
final int[] arr = {23, 42};
|
||||
Assert.assertEquals((int) invokeWithFixedKey(publicLookup, GET_ELEMENT, 0, mt, arr), 23);
|
||||
Assert.assertEquals((int) invokeWithFixedKey(publicLookup, GET_ELEMENT, 1, mt, arr), 42);
|
||||
try {
|
||||
invokeWithFixedKey(publicLookup, GET_ELEMENT, -1, mt, arr);
|
||||
throw new RuntimeException("expected ArrayIndexOutOfBoundsException");
|
||||
} catch (final ArrayIndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
invokeWithFixedKey(publicLookup, GET_ELEMENT, arr.length, mt, arr);
|
||||
throw new RuntimeException("expected ArrayIndexOutOfBoundsException");
|
||||
} catch (final ArrayIndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
final List<Integer> list = new ArrayList<>();
|
||||
list.add(23);
|
||||
list.add(430);
|
||||
list.add(-4354);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
Assert.assertEquals((int) invokeWithFixedKey(publicLookup, GET_ELEMENT, i, mt, list), (int) list.get(i));
|
||||
}
|
||||
try {
|
||||
invokeWithFixedKey(publicLookup, GET_ELEMENT, -1, mt, list);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
invokeWithFixedKey(publicLookup, GET_ELEMENT, list.size(), mt, list);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void setElementTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(void.class, Object.class, int.class, int.class);
|
||||
final CallSite cs = createCallSite(publicLookup, SET_ELEMENT, mt);
|
||||
|
||||
final int[] arr = {23, 42};
|
||||
cs.getTarget().invoke(arr, 0, 0);
|
||||
Assert.assertEquals(arr[0], 0);
|
||||
cs.getTarget().invoke(arr, 1, -5);
|
||||
Assert.assertEquals(arr[1], -5);
|
||||
|
||||
try {
|
||||
cs.getTarget().invoke(arr, -1, 12);
|
||||
throw new RuntimeException("expected ArrayIndexOutOfBoundsException");
|
||||
} catch (final ArrayIndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
cs.getTarget().invoke(arr, arr.length, 20);
|
||||
throw new RuntimeException("expected ArrayIndexOutOfBoundsException");
|
||||
} catch (final ArrayIndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
final List<Integer> list = new ArrayList<>();
|
||||
list.add(23);
|
||||
list.add(430);
|
||||
list.add(-4354);
|
||||
|
||||
cs.getTarget().invoke(list, 0, -list.get(0));
|
||||
Assert.assertEquals((int) list.get(0), -23);
|
||||
cs.getTarget().invoke(list, 1, -430);
|
||||
Assert.assertEquals((int) list.get(1), -430);
|
||||
cs.getTarget().invoke(list, 2, 4354);
|
||||
Assert.assertEquals((int) list.get(2), 4354);
|
||||
try {
|
||||
cs.getTarget().invoke(list, -1, 343);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
cs.getTarget().invoke(list, list.size(), 43543);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void setElementWithFixedKeyTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(void.class, Object.class, int.class);
|
||||
|
||||
final int[] arr = {23, 42};
|
||||
invokeWithFixedKey(publicLookup, SET_ELEMENT, 0, mt, arr, 0);
|
||||
Assert.assertEquals(arr[0], 0);
|
||||
invokeWithFixedKey(publicLookup, SET_ELEMENT, 1, mt, arr, -5);
|
||||
Assert.assertEquals(arr[1], -5);
|
||||
|
||||
try {
|
||||
invokeWithFixedKey(publicLookup, SET_ELEMENT, -1, mt, arr, 12);
|
||||
throw new RuntimeException("expected ArrayIndexOutOfBoundsException");
|
||||
} catch (final ArrayIndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
invokeWithFixedKey(publicLookup, SET_ELEMENT, arr.length, mt, arr, 20);
|
||||
throw new RuntimeException("expected ArrayIndexOutOfBoundsException");
|
||||
} catch (final ArrayIndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
final List<Integer> list = new ArrayList<>();
|
||||
list.add(23);
|
||||
list.add(430);
|
||||
list.add(-4354);
|
||||
|
||||
invokeWithFixedKey(publicLookup, SET_ELEMENT, 0, mt, list, -list.get(0));
|
||||
Assert.assertEquals((int) list.get(0), -23);
|
||||
invokeWithFixedKey(publicLookup, SET_ELEMENT, 1, mt, list, -430);
|
||||
Assert.assertEquals((int) list.get(1), -430);
|
||||
invokeWithFixedKey(publicLookup, SET_ELEMENT, 2, mt, list, 4354);
|
||||
Assert.assertEquals((int) list.get(2), 4354);
|
||||
try {
|
||||
invokeWithFixedKey(publicLookup, SET_ELEMENT, -1, mt, list, 343);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
invokeWithFixedKey(publicLookup, SET_ELEMENT, list.size(), mt, list, 43543);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void newObjectTest(final boolean publicLookup) {
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class);
|
||||
final CallSite cs = createCallSite(publicLookup, NEW, mt);
|
||||
|
||||
Object obj = null;
|
||||
try {
|
||||
obj = cs.getTarget().invoke(StaticClass.forClass(Date.class));
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
|
||||
Assert.assertTrue(obj instanceof Date);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void staticPropertyTest(final boolean publicLookup) {
|
||||
final MethodType mt = MethodType.methodType(Object.class, Class.class);
|
||||
final CallSite cs = createCallSite(publicLookup, GET_PROPERTY, "static", mt);
|
||||
|
||||
Object obj = null;
|
||||
try {
|
||||
obj = cs.getTarget().invoke(Object.class);
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
|
||||
Assert.assertTrue(obj instanceof StaticClass);
|
||||
Assert.assertEquals(((StaticClass) obj).getRepresentedClass(), Object.class);
|
||||
|
||||
try {
|
||||
obj = cs.getTarget().invoke(Date.class);
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
|
||||
Assert.assertTrue(obj instanceof StaticClass);
|
||||
Assert.assertEquals(((StaticClass) obj).getRepresentedClass(), Date.class);
|
||||
|
||||
try {
|
||||
obj = cs.getTarget().invoke(Object[].class);
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
|
||||
Assert.assertTrue(obj instanceof StaticClass);
|
||||
Assert.assertEquals(((StaticClass) obj).getRepresentedClass(), Object[].class);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void instanceMethodCallTest(final boolean publicLookup) {
|
||||
final CallSite cs = createGetMethodCallSite(publicLookup, "getClass");
|
||||
final MethodType mt2 = MethodType.methodType(Class.class, Object.class, Object.class);
|
||||
final CallSite cs2 = createCallSite(publicLookup, CALL, mt2);
|
||||
|
||||
Object method = null;
|
||||
try {
|
||||
method = cs.getTarget().invoke(new Date());
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
|
||||
Assert.assertNotNull(method);
|
||||
Assert.assertTrue(BeansLinker.isDynamicMethod(method));
|
||||
Class clz = null;
|
||||
try {
|
||||
clz = (Class) cs2.getTarget().invoke(method, new Date());
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
|
||||
Assert.assertEquals(clz, Date.class);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void staticMethodCallTest(final boolean publicLookup) {
|
||||
final CallSite cs = createGetMethodCallSite(publicLookup, "getProperty");
|
||||
final MethodType mt2 = MethodType.methodType(String.class, Object.class, Object.class, String.class);
|
||||
final CallSite cs2 = createCallSite(publicLookup, CALL, mt2);
|
||||
|
||||
Object method = null;
|
||||
try {
|
||||
method = cs.getTarget().invoke(StaticClass.forClass(System.class));
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
|
||||
Assert.assertNotNull(method);
|
||||
Assert.assertTrue(BeansLinker.isDynamicMethod(method));
|
||||
|
||||
String str = null;
|
||||
try {
|
||||
str = (String) cs2.getTarget().invoke(method, null, "os.name");
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
Assert.assertEquals(str, System.getProperty("os.name"));
|
||||
}
|
||||
|
||||
// try calling System.getenv and expect security exception
|
||||
@Test(dataProvider = "flags")
|
||||
public void systemGetenvTest(final boolean publicLookup) {
|
||||
final CallSite cs1 = createGetMethodCallSite(publicLookup, "getenv");
|
||||
final CallSite cs2 = createCallSite(publicLookup, CALL, MethodType.methodType(Object.class, Object.class, Object.class));
|
||||
|
||||
try {
|
||||
final Object method = cs1.getTarget().invoke(StaticClass.forClass(System.class));
|
||||
cs2.getTarget().invoke(method, StaticClass.forClass(System.class));
|
||||
throw new RuntimeException("should not reach here in any case!");
|
||||
} catch (final Throwable th) {
|
||||
Assert.assertTrue(th instanceof SecurityException);
|
||||
}
|
||||
}
|
||||
|
||||
// try getting a specific sensitive System property and expect security exception
|
||||
@Test(dataProvider = "flags")
|
||||
public void systemGetPropertyTest(final boolean publicLookup) {
|
||||
final CallSite cs1 = createGetMethodCallSite(publicLookup, "getProperty");
|
||||
final CallSite cs2 = createCallSite(publicLookup, CALL, MethodType.methodType(String.class, Object.class, Object.class, String.class));
|
||||
|
||||
try {
|
||||
final Object method = cs1.getTarget().invoke(StaticClass.forClass(System.class));
|
||||
cs2.getTarget().invoke(method, StaticClass.forClass(System.class), "java.home");
|
||||
throw new RuntimeException("should not reach here in any case!");
|
||||
} catch (final Throwable th) {
|
||||
Assert.assertTrue(th instanceof SecurityException);
|
||||
}
|
||||
}
|
||||
|
||||
// check a @CallerSensitive API and expect appropriate access check exception
|
||||
@Test(dataProvider = "flags")
|
||||
public void systemLoadLibraryTest(final boolean publicLookup) {
|
||||
final CallSite cs1 = createGetMethodCallSite(publicLookup, "loadLibrary");
|
||||
final CallSite cs2 = createCallSite(publicLookup, CALL, MethodType.methodType(void.class, Object.class, Object.class, String.class));
|
||||
|
||||
try {
|
||||
final Object method = cs1.getTarget().invoke(StaticClass.forClass(System.class));
|
||||
cs2.getTarget().invoke(method, StaticClass.forClass(System.class), "foo");
|
||||
throw new RuntimeException("should not reach here in any case!");
|
||||
} catch (final Throwable th) {
|
||||
if (publicLookup) {
|
||||
Assert.assertTrue(th instanceof IllegalAccessError);
|
||||
} else {
|
||||
Assert.assertTrue(th instanceof AccessControlException, "Expected AccessControlException, got " + th.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void removeElementFromListTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(void.class, Object.class, int.class);
|
||||
final CallSite cs = createCallSite(publicLookup, REMOVE_ELEMENT, mt);
|
||||
|
||||
final List<Integer> list = new ArrayList<>(List.of(23, 430, -4354));
|
||||
|
||||
cs.getTarget().invoke(list, 1);
|
||||
Assert.assertEquals(list, List.of(23, -4354));
|
||||
cs.getTarget().invoke(list, 1);
|
||||
Assert.assertEquals(list, List.of(23));
|
||||
cs.getTarget().invoke(list, 0);
|
||||
Assert.assertEquals(list, List.of());
|
||||
try {
|
||||
cs.getTarget().invoke(list, -1);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
cs.getTarget().invoke(list, list.size());
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void removeElementFromListWithFixedKeyTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(void.class, Object.class);
|
||||
|
||||
final List<Integer> list = new ArrayList<>(List.of(23, 430, -4354));
|
||||
|
||||
createCallSite(publicLookup, REMOVE_ELEMENT.named(1), mt).getTarget().invoke(list);
|
||||
Assert.assertEquals(list, List.of(23, -4354));
|
||||
createCallSite(publicLookup, REMOVE_ELEMENT.named(1), mt).getTarget().invoke(list);
|
||||
Assert.assertEquals(list, List.of(23));
|
||||
createCallSite(publicLookup, REMOVE_ELEMENT.named(0), mt).getTarget().invoke(list);
|
||||
Assert.assertEquals(list, List.of());
|
||||
try {
|
||||
createCallSite(publicLookup, REMOVE_ELEMENT.named(-1), mt).getTarget().invoke(list);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
|
||||
try {
|
||||
createCallSite(publicLookup, REMOVE_ELEMENT.named(list.size()), mt).getTarget().invoke(list);
|
||||
throw new RuntimeException("expected IndexOutOfBoundsException");
|
||||
} catch (final IndexOutOfBoundsException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void removeElementFromMapTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(void.class, Object.class, Object.class);
|
||||
final CallSite cs = createCallSite(publicLookup, REMOVE_ELEMENT, mt);
|
||||
|
||||
final Map<String, String> map = new HashMap<>(Map.of("k1", "v1", "k2", "v2", "k3", "v3"));
|
||||
|
||||
cs.getTarget().invoke(map, "k2");
|
||||
Assert.assertEquals(map, Map.of("k1", "v1", "k3", "v3"));
|
||||
cs.getTarget().invoke(map, "k4");
|
||||
Assert.assertEquals(map, Map.of("k1", "v1", "k3", "v3"));
|
||||
cs.getTarget().invoke(map, "k1");
|
||||
Assert.assertEquals(map, Map.of("k3", "v3"));
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void removeElementFromMapWithFixedKeyTest(final boolean publicLookup) throws Throwable {
|
||||
final MethodType mt = MethodType.methodType(void.class, Object.class);
|
||||
|
||||
final Map<String, String> map = new HashMap<>(Map.of("k1", "v1", "k2", "v2", "k3", "v3"));
|
||||
|
||||
createCallSite(publicLookup, REMOVE_ELEMENT.named("k2"), mt).getTarget().invoke(map);
|
||||
Assert.assertEquals(map, Map.of("k1", "v1", "k3", "v3"));
|
||||
createCallSite(publicLookup, REMOVE_ELEMENT.named("k4"), mt).getTarget().invoke(map);
|
||||
Assert.assertEquals(map, Map.of("k1", "v1", "k3", "v3"));
|
||||
createCallSite(publicLookup, REMOVE_ELEMENT.named("k1"), mt).getTarget().invoke(map);
|
||||
Assert.assertEquals(map, Map.of("k3", "v3"));
|
||||
}
|
||||
}
|
333
test/jdk/jdk/dynalink/BeansLinkerTest.java
Normal file
333
test/jdk/jdk/dynalink/BeansLinkerTest.java
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import static jdk.dynalink.StandardNamespace.ELEMENT;
|
||||
import static jdk.dynalink.StandardNamespace.METHOD;
|
||||
import static jdk.dynalink.StandardNamespace.PROPERTY;
|
||||
import static jdk.dynalink.StandardOperation.CALL;
|
||||
import static jdk.dynalink.StandardOperation.GET;
|
||||
import static jdk.dynalink.StandardOperation.SET;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.dynalink.CallSiteDescriptor;
|
||||
import jdk.dynalink.DynamicLinkerFactory;
|
||||
import jdk.dynalink.Namespace;
|
||||
import jdk.dynalink.NamespaceOperation;
|
||||
import jdk.dynalink.NoSuchDynamicMethodException;
|
||||
import jdk.dynalink.Operation;
|
||||
import jdk.dynalink.beans.StaticClass;
|
||||
import jdk.dynalink.support.SimpleRelinkableCallSite;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @run testng BeansLinkerTest
|
||||
*/
|
||||
public class BeansLinkerTest {
|
||||
public static class Bean1 {
|
||||
public final int answer = 42;
|
||||
|
||||
public String getName() {
|
||||
return "bean1";
|
||||
}
|
||||
|
||||
public String someMethod(final String x) {
|
||||
return x + "-foo";
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testPublicFieldPropertyUnnamedGetter() {
|
||||
testGetterPermutations(PROPERTY, (op) -> Assert.assertEquals(42, call(op, new Bean1(), "answer")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testPublicFieldPropertyNamedGetter() {
|
||||
testGetterPermutations(PROPERTY, (op) -> Assert.assertEquals(42, call(op.named("answer"), new Bean1())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testGetterPropertyUnnamedGetter() {
|
||||
testGetterPermutations(PROPERTY, (op) -> Assert.assertEquals("bean1", call(op, new Bean1(), "name")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testGetterPropertyNamedGetter() {
|
||||
testGetterPermutations(PROPERTY, (op) -> Assert.assertEquals("bean1", call(op.named("name"), new Bean1())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testMethodUnnamedGetter() {
|
||||
testGetterPermutations(METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(op, new Bean1(), "someMethod"), new Bean1(), "bar")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testMethodNamedGetter() {
|
||||
testGetterPermutations(METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(op.named("someMethod"), new Bean1()), new Bean1(), "bar")));
|
||||
}
|
||||
|
||||
private static final Map<String, String> MAP1 = new HashMap<>();
|
||||
static {
|
||||
MAP1.put("foo", "bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testElementUnnamedGetter() {
|
||||
testGetterPermutations(ELEMENT, (op) -> Assert.assertEquals("bar", call(op, MAP1, "foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testElementNamedGetter() {
|
||||
testGetterPermutations(ELEMENT, (op) -> Assert.assertEquals("bar", call(op.named("foo"), MAP1)));
|
||||
}
|
||||
|
||||
public static class Bean2 {
|
||||
public int answer;
|
||||
private String name;
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testUnnamedFieldSetter() {
|
||||
testSetterPermutations(PROPERTY, (op) -> {
|
||||
final Bean2 bean2 = new Bean2();
|
||||
call(op, bean2, "answer", 12);
|
||||
Assert.assertEquals(bean2.answer, 12);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testNamedFieldSetter() {
|
||||
testSetterPermutations(PROPERTY, (op) -> {
|
||||
final Bean2 bean2 = new Bean2();
|
||||
call(op.named("answer"), bean2, 14);
|
||||
Assert.assertEquals(bean2.answer, 14);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testUnnamedPropertySetter() {
|
||||
testSetterPermutations(PROPERTY, (op) -> {
|
||||
final Bean2 bean2 = new Bean2();
|
||||
call(op, bean2, "name", "boo");
|
||||
Assert.assertEquals(bean2.name, "boo");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testNamedPropertySetter() {
|
||||
testSetterPermutations(PROPERTY, (op) -> {
|
||||
final Bean2 bean2 = new Bean2();
|
||||
call(op.named("name"), bean2, "blah");
|
||||
Assert.assertEquals(bean2.name, "blah");
|
||||
});
|
||||
}
|
||||
|
||||
private static final Pattern GET_ELEMENT_THEN_PROPERTY_PATTERN = Pattern.compile(".*ELEMENT.*PROPERTY.*");
|
||||
|
||||
@Test
|
||||
public static void testUnnamedElementAndPropertyGetter() {
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
map.put("empty", true);
|
||||
testGetterPermutations(GET_ELEMENT_THEN_PROPERTY_PATTERN, 4, (op) -> Assert.assertEquals(true, call(op, map, "empty")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testNamedElementAndPropertyGetter() {
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
map.put("empty", true);
|
||||
testGetterPermutations(GET_ELEMENT_THEN_PROPERTY_PATTERN, 4, (op) -> Assert.assertEquals(true, call(op.named("empty"), map)));
|
||||
}
|
||||
|
||||
private static final Pattern GET_PROPERTY_THEN_ELEMENT_PATTERN = Pattern.compile(".*PROPERTY.*ELEMENT.*");
|
||||
|
||||
@Test
|
||||
public static void testUnnamedPropertyAndElementGetter() {
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
map.put("empty", true);
|
||||
testGetterPermutations(GET_PROPERTY_THEN_ELEMENT_PATTERN, 4, (op) -> Assert.assertEquals(false, call(op, map, "empty")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testNamedPropertyAndElementGetter() {
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
map.put("empty", true);
|
||||
testGetterPermutations(GET_PROPERTY_THEN_ELEMENT_PATTERN, 4, (op) -> Assert.assertEquals(false, call(op.named("empty"), map)));
|
||||
}
|
||||
|
||||
public static class MapWithProperty extends HashMap<String, Object> {
|
||||
private String name;
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testUnnamedPropertyAndElementSetter() {
|
||||
final MapWithProperty map = new MapWithProperty();
|
||||
map.put("name", "element");
|
||||
|
||||
call(SET.withNamespaces(PROPERTY, ELEMENT), map, "name", "property");
|
||||
Assert.assertEquals("property", map.name);
|
||||
Assert.assertEquals("element", map.get("name"));
|
||||
|
||||
call(SET.withNamespaces(ELEMENT, PROPERTY), map, "name", "element2");
|
||||
Assert.assertEquals("property", map.name);
|
||||
Assert.assertEquals("element2", map.get("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testMissingMembersAtLinkTime() {
|
||||
testPermutations(GETTER_PERMUTATIONS, (op) -> expectNoSuchDynamicMethodException(()-> call(op.named("foo"), new Object())));
|
||||
testPermutations(SETTER_PERMUTATIONS, (op) -> expectNoSuchDynamicMethodException(()-> call(op.named("foo"), new Object(), "newValue")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testMissingMembersAtRunTime() {
|
||||
call(GET.withNamespace(ELEMENT), new ArrayList<>(), "foo");
|
||||
Stream.of(new HashMap(), new ArrayList(), new Object[0]).forEach((receiver) -> {
|
||||
testPermutations(GETTER_PERMUTATIONS, (op) -> { System.err.println(op + " " + receiver.getClass().getName()); Assert.assertNull(call(op, receiver, "foo"));});
|
||||
// No assertion for the setter; we just expect it to silently succeed
|
||||
testPermutations(SETTER_PERMUTATIONS, (op) -> call(op, receiver, "foo", "newValue"));
|
||||
});
|
||||
}
|
||||
|
||||
public static class A {
|
||||
public static class Inner {}
|
||||
}
|
||||
|
||||
public static class B extends A {
|
||||
public static class Inner {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testInnerClassGetter() {
|
||||
Object inner1 = call(GET.withNamespace(PROPERTY), StaticClass.forClass(A.class), "Inner");
|
||||
Assert.assertTrue(inner1 instanceof StaticClass);
|
||||
Assert.assertEquals(A.Inner.class, ((StaticClass) inner1).getRepresentedClass());
|
||||
|
||||
Object inner2 = call(GET.withNamespace(PROPERTY), StaticClass.forClass(B.class), "Inner");
|
||||
Assert.assertTrue(inner2 instanceof StaticClass);
|
||||
Assert.assertEquals(B.Inner.class, ((StaticClass) inner2).getRepresentedClass());
|
||||
}
|
||||
|
||||
private static void expectNoSuchDynamicMethodException(final Runnable r) {
|
||||
try {
|
||||
r.run();
|
||||
Assert.fail("Should've thrown NoSuchDynamicMethodException");
|
||||
} catch(final NoSuchDynamicMethodException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private static final NamespaceOperation[] GETTER_PERMUTATIONS = new NamespaceOperation[] {
|
||||
GET.withNamespaces(PROPERTY),
|
||||
GET.withNamespaces(METHOD),
|
||||
GET.withNamespaces(ELEMENT),
|
||||
GET.withNamespaces(PROPERTY, ELEMENT),
|
||||
GET.withNamespaces(PROPERTY, METHOD),
|
||||
GET.withNamespaces(ELEMENT, PROPERTY),
|
||||
GET.withNamespaces(ELEMENT, METHOD),
|
||||
GET.withNamespaces(METHOD, PROPERTY),
|
||||
GET.withNamespaces(METHOD, ELEMENT),
|
||||
GET.withNamespaces(PROPERTY, ELEMENT, METHOD),
|
||||
GET.withNamespaces(PROPERTY, METHOD, ELEMENT),
|
||||
GET.withNamespaces(ELEMENT, PROPERTY, METHOD),
|
||||
GET.withNamespaces(ELEMENT, METHOD, PROPERTY),
|
||||
GET.withNamespaces(METHOD, PROPERTY, ELEMENT),
|
||||
GET.withNamespaces(METHOD, ELEMENT, PROPERTY)
|
||||
};
|
||||
|
||||
private static final NamespaceOperation[] SETTER_PERMUTATIONS = new NamespaceOperation[] {
|
||||
SET.withNamespaces(PROPERTY),
|
||||
SET.withNamespaces(ELEMENT),
|
||||
SET.withNamespaces(PROPERTY, ELEMENT),
|
||||
SET.withNamespaces(ELEMENT, PROPERTY)
|
||||
};
|
||||
|
||||
private static void testPermutations(final NamespaceOperation[] ops, final Operation requiredOp, final Namespace requiredNamespace, final int expectedCount, final Consumer<NamespaceOperation> test) {
|
||||
testPermutationsWithFilter(ops, (op)->NamespaceOperation.contains(op, requiredOp, requiredNamespace), expectedCount, test);
|
||||
}
|
||||
|
||||
private static void testPermutations(final NamespaceOperation[] ops, final Pattern regex, final int expectedCount, final Consumer<NamespaceOperation> test) {
|
||||
testPermutationsWithFilter(ops, (op)->regex.matcher(op.toString()).matches(), expectedCount, test);
|
||||
}
|
||||
|
||||
private static void testPermutations(final NamespaceOperation[] ops, final Consumer<NamespaceOperation> test) {
|
||||
testPermutationsWithFilter(ops, (op)->true, ops.length, test);
|
||||
}
|
||||
|
||||
private static void testPermutationsWithFilter(final NamespaceOperation[] ops, final Predicate<NamespaceOperation> filter, final int expectedCount, final Consumer<NamespaceOperation> test) {
|
||||
final int[] counter = new int[1];
|
||||
Stream.of(ops).filter(filter).forEach((op)-> { counter[0]++; test.accept(op); });
|
||||
Assert.assertEquals(counter[0], expectedCount);
|
||||
}
|
||||
|
||||
private static void testGetterPermutations(final Namespace requiredNamespace, final Consumer<NamespaceOperation> test) {
|
||||
testPermutations(GETTER_PERMUTATIONS, GET, requiredNamespace, 11, test);
|
||||
}
|
||||
|
||||
private static void testGetterPermutations(final Pattern regex, final int expectedCount, final Consumer<NamespaceOperation> test) {
|
||||
testPermutations(GETTER_PERMUTATIONS, regex, expectedCount, test);
|
||||
}
|
||||
|
||||
private static void testSetterPermutations(final Namespace requiredNamespace, final Consumer<NamespaceOperation> test) {
|
||||
testPermutations(SETTER_PERMUTATIONS, SET, requiredNamespace, 3, test);
|
||||
}
|
||||
|
||||
private static Object call(final Operation op, final Object... args) {
|
||||
try {
|
||||
return new DynamicLinkerFactory().createLinker().link(
|
||||
new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), op, t(args.length))))
|
||||
.dynamicInvoker().invokeWithArguments(args);
|
||||
} catch (final Error|RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object call(final Object... args) {
|
||||
return call(CALL, args);
|
||||
}
|
||||
|
||||
private static MethodType t(final int argCount) {
|
||||
return MethodType.methodType(Object.class, Collections.nCopies(argCount, Object.class));
|
||||
}
|
||||
}
|
119
test/jdk/jdk/dynalink/CallSiteTest.java
Normal file
119
test/jdk/jdk/dynalink/CallSiteTest.java
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import static jdk.dynalink.StandardNamespace.PROPERTY;
|
||||
import static jdk.dynalink.StandardOperation.GET;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.ArrayList;
|
||||
import jdk.dynalink.CallSiteDescriptor;
|
||||
import jdk.dynalink.DynamicLinker;
|
||||
import jdk.dynalink.DynamicLinkerFactory;
|
||||
import jdk.dynalink.Operation;
|
||||
import jdk.dynalink.linker.GuardedInvocation;
|
||||
import jdk.dynalink.support.SimpleRelinkableCallSite;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @run testng CallSiteTest
|
||||
*/
|
||||
public class CallSiteTest {
|
||||
private static final Operation GET_PROPERTY = GET.withNamespace(PROPERTY);
|
||||
|
||||
@Test
|
||||
public void testInitialize() {
|
||||
final DynamicLinkerFactory factory = new DynamicLinkerFactory();
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class);
|
||||
final boolean[] initializeCalled = { Boolean.FALSE };
|
||||
linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), GET_PROPERTY.named("DO_NOT_CARE"), mt)) {
|
||||
@Override
|
||||
public void initialize(final MethodHandle relinkAndInvoke) {
|
||||
initializeCalled[0] = Boolean.TRUE;
|
||||
super.initialize(relinkAndInvoke);
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertTrue(initializeCalled[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRelink() {
|
||||
final DynamicLinkerFactory factory = new DynamicLinkerFactory();
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class);
|
||||
final boolean[] relinkCalled = { Boolean.FALSE };
|
||||
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), GET_PROPERTY.named("class"), mt)) {
|
||||
@Override
|
||||
public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) {
|
||||
relinkCalled[0] = Boolean.TRUE;
|
||||
super.relink(guardedInvocation, relinkAndInvoke);
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertFalse(relinkCalled[0]);
|
||||
try {
|
||||
cs.getTarget().invoke(new Object());
|
||||
} catch (final Throwable th) {}
|
||||
|
||||
Assert.assertTrue(relinkCalled[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResetAndRelink() {
|
||||
final DynamicLinkerFactory factory = new DynamicLinkerFactory();
|
||||
factory.setUnstableRelinkThreshold(1);
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class);
|
||||
final boolean[] resetAndRelinkCalled = { Boolean.FALSE };
|
||||
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), GET_PROPERTY.named("length"), mt)) {
|
||||
@Override
|
||||
public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) {
|
||||
resetAndRelinkCalled[0] = Boolean.TRUE;
|
||||
super.resetAndRelink(guardedInvocation, relinkAndInvoke);
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertFalse(resetAndRelinkCalled[0]);
|
||||
try {
|
||||
cs.getTarget().invoke(new Object[] {});
|
||||
} catch (final Throwable th) {}
|
||||
|
||||
Assert.assertFalse(resetAndRelinkCalled[0]);
|
||||
try {
|
||||
cs.getTarget().invoke(new ArrayList<Object>());
|
||||
} catch (final Throwable th) {}
|
||||
|
||||
Assert.assertTrue(resetAndRelinkCalled[0]);
|
||||
}
|
||||
}
|
39
test/jdk/jdk/dynalink/CallerSensitiveTest.java
Normal file
39
test/jdk/jdk/dynalink/CallerSensitiveTest.java
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import jdk.dynalink.beans.BeansLinker;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @build ClassLoaderAware
|
||||
* @run testng CallerSensitiveTest
|
||||
*/
|
||||
public class CallerSensitiveTest {
|
||||
@Test
|
||||
public void testCallerSensitive() {
|
||||
new BeansLinker().getLinkerForClass(ClassLoaderAware.class);
|
||||
}
|
||||
}
|
29
test/jdk/jdk/dynalink/ClassLoaderAware.java
Normal file
29
test/jdk/jdk/dynalink/ClassLoaderAware.java
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
public interface ClassLoaderAware {
|
||||
public ClassLoader getContextClassLoader();
|
||||
public void checkMemberAccess(Class<?> clazz, int which);
|
||||
}
|
90
test/jdk/jdk/dynalink/LinkedCallSiteLocationTest.java
Normal file
90
test/jdk/jdk/dynalink/LinkedCallSiteLocationTest.java
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.dynalink.CallSiteDescriptor;
|
||||
import jdk.dynalink.DynamicLinker;
|
||||
import jdk.dynalink.DynamicLinkerFactory;
|
||||
import jdk.dynalink.Operation;
|
||||
import jdk.dynalink.StandardNamespace;
|
||||
import jdk.dynalink.StandardOperation;
|
||||
import jdk.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.dynalink.support.SimpleRelinkableCallSite;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @run testng LinkedCallSiteLocationTest
|
||||
*/
|
||||
public class LinkedCallSiteLocationTest {
|
||||
private static final Operation GET_METHOD = StandardOperation.GET.withNamespace(StandardNamespace.METHOD);
|
||||
@Test
|
||||
public void testLinkedCallSiteLocation() throws Throwable {
|
||||
final StackTraceElement[] lastLinked = new StackTraceElement[1];
|
||||
|
||||
final GuardingDynamicLinker testLinker =
|
||||
(r, s) -> { lastLinked[0] = DynamicLinker.getLinkedCallSiteLocation(); return null; };
|
||||
|
||||
final DynamicLinkerFactory factory = new DynamicLinkerFactory();
|
||||
factory.setPrioritizedLinker(testLinker);
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final SimpleRelinkableCallSite callSite = new SimpleRelinkableCallSite(
|
||||
new CallSiteDescriptor(
|
||||
MethodHandles.lookup(),
|
||||
GET_METHOD.named("foo"),
|
||||
MethodType.methodType(void.class, Object.class)));
|
||||
linker.link(callSite);
|
||||
|
||||
// Test initial linking
|
||||
callSite.dynamicInvoker().invoke(new TestClass1()); final int l1 = getLineNumber();
|
||||
assertLocation(lastLinked[0], l1);
|
||||
|
||||
// Test relinking
|
||||
callSite.dynamicInvoker().invoke(new TestClass2()); final int l2 = getLineNumber();
|
||||
assertLocation(lastLinked[0], l2);
|
||||
}
|
||||
|
||||
private void assertLocation(final StackTraceElement frame, final int lineNumber) {
|
||||
Assert.assertNotNull(frame);
|
||||
Assert.assertEquals(frame.getLineNumber(), lineNumber);
|
||||
Assert.assertEquals(frame.getClassName(), this.getClass().getName());
|
||||
}
|
||||
|
||||
private static int getLineNumber() {
|
||||
return StackWalker.getInstance().walk(s -> s.skip(1).findFirst().get().getLineNumber());
|
||||
}
|
||||
|
||||
public static class TestClass1 {
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestClass2 {
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
}
|
273
test/jdk/jdk/dynalink/LookupTest.java
Normal file
273
test/jdk/jdk/dynalink/LookupTest.java
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.dynalink.linker.support.Lookup;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @run testng LookupTest
|
||||
*/
|
||||
public class LookupTest {
|
||||
private static final MethodHandles.Lookup MY_LOOKUP = MethodHandles.lookup();
|
||||
|
||||
private static MethodHandles.Lookup getLookup(final boolean publicLookup) {
|
||||
return publicLookup? MethodHandles.publicLookup() : MY_LOOKUP;
|
||||
}
|
||||
|
||||
// test constructors, methods used for lookup
|
||||
@SuppressWarnings("unused")
|
||||
public LookupTest() {}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private LookupTest(final int unused) {}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void privateFunc() {}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected void protectedFunc() {}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static void privateStaticFunc() {}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final int myIntField = 0;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@DataProvider
|
||||
private static Object[][] flags() {
|
||||
return new Object[][]{
|
||||
{Boolean.FALSE},
|
||||
{Boolean.TRUE}
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void unreflectTest(final boolean publicLookup) throws NoSuchMethodException {
|
||||
final MethodHandle mh = Lookup.unreflect(getLookup(publicLookup), LookupTest.class.getMethod("unreflectTest", Boolean.TYPE));
|
||||
Assert.assertNotNull(mh);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unreflectTest2() throws NoSuchMethodException {
|
||||
final MethodHandle mh = Lookup.PUBLIC.unreflect(LookupTest.class.getMethod("unreflectTest", Boolean.TYPE));
|
||||
Assert.assertNotNull(mh);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void unreflectNegativeTest(final boolean publicLookup) throws NoSuchMethodException {
|
||||
try {
|
||||
final MethodHandle mh = Lookup.unreflect(getLookup(publicLookup),
|
||||
LookupTest.class.getDeclaredMethod("privateFunc"));
|
||||
if (publicLookup) {
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
}
|
||||
Assert.assertNotNull(mh);
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(publicLookup);
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unreflectNegativeTest2() throws NoSuchMethodException {
|
||||
try {
|
||||
Lookup.PUBLIC.unreflect(LookupTest.class.getDeclaredMethod("privateFunc"));
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void unreflectConstructorTest(final boolean publicLookup) throws NoSuchMethodException {
|
||||
final MethodHandle mh = Lookup.unreflectConstructor(getLookup(publicLookup), LookupTest.class.getConstructor());
|
||||
Assert.assertNotNull(mh);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unreflectConstructorTest2() throws NoSuchMethodException {
|
||||
final MethodHandle mh = Lookup.PUBLIC.unreflectConstructor(LookupTest.class.getConstructor());
|
||||
Assert.assertNotNull(mh);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void unreflectConstructorNegativeTest(final boolean publicLookup) throws NoSuchMethodException {
|
||||
try {
|
||||
final MethodHandle mh = Lookup.unreflectConstructor(getLookup(publicLookup),
|
||||
LookupTest.class.getDeclaredConstructor(Integer.TYPE));
|
||||
if (publicLookup) {
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
}
|
||||
Assert.assertNotNull(mh);
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(publicLookup);
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unreflectConstructorNegativeTest2() throws NoSuchMethodException {
|
||||
try {
|
||||
Lookup.PUBLIC.unreflectConstructor(
|
||||
LookupTest.class.getDeclaredConstructor(Integer.TYPE));
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void findOwnStaticTest(final boolean publicLookup) {
|
||||
try {
|
||||
final MethodHandle mh = Lookup.findOwnStatic(getLookup(publicLookup), "getLookup",
|
||||
MethodHandles.Lookup.class, Boolean.TYPE);
|
||||
if (publicLookup) {
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
}
|
||||
Assert.assertNotNull(mh);
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(publicLookup);
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOwnStaticTest2() {
|
||||
try {
|
||||
Lookup.PUBLIC.findStatic(LookupTest.class, "getLookup",
|
||||
MethodType.methodType(MethodHandles.Lookup.class, Boolean.TYPE));
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void findOwnSepcialTest(final boolean publicLookup) {
|
||||
try {
|
||||
final MethodHandle mh = Lookup.findOwnSpecial(getLookup(publicLookup), "privateFunc", Void.TYPE);
|
||||
if (publicLookup) {
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
}
|
||||
Assert.assertNotNull(mh);
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(publicLookup);
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOwnSepcialTest2() {
|
||||
try {
|
||||
Lookup.PUBLIC.findOwnSpecial("privateFunc", Void.TYPE);
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void findGetterTest(final boolean publicLookup) {
|
||||
try {
|
||||
final MethodHandle mh = new Lookup(getLookup(publicLookup)).findGetter(LookupTest.class, "myIntField", Integer.TYPE);
|
||||
if (publicLookup) {
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
}
|
||||
Assert.assertNotNull(mh);
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(publicLookup);
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findGetterTest2() {
|
||||
try {
|
||||
Lookup.PUBLIC.findGetter(LookupTest.class, "myIntField", Integer.TYPE);
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void findVirtualTest(final boolean publicLookup) {
|
||||
try {
|
||||
final MethodHandle mh = new Lookup(getLookup(publicLookup)).findVirtual(LookupTest.class, "protectedFunc",
|
||||
MethodType.methodType(Void.TYPE));
|
||||
if (publicLookup) {
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
}
|
||||
Assert.assertNotNull(mh);
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(publicLookup);
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findVirtualTest2() {
|
||||
try {
|
||||
Lookup.PUBLIC.findVirtual(LookupTest.class, "protectedFunc",
|
||||
MethodType.methodType(Void.TYPE));
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "flags")
|
||||
public void findStaticTest(final boolean publicLookup) {
|
||||
try {
|
||||
final MethodHandle mh = new Lookup(getLookup(publicLookup)).findStatic(LookupTest.class, "privateStaticFunc",
|
||||
MethodType.methodType(Void.TYPE));
|
||||
if (publicLookup) {
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
}
|
||||
Assert.assertNotNull(mh);
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(publicLookup);
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findStaticTest2() {
|
||||
try {
|
||||
Lookup.PUBLIC.findStatic(LookupTest.class, "privateStaticFunc",
|
||||
MethodType.methodType(Void.TYPE));
|
||||
throw new RuntimeException("should have thrown Error");
|
||||
} catch (final Error err) {
|
||||
Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
TestGuardingDynamicLinkerExporter
|
66
test/jdk/jdk/dynalink/TestGuardingDynamicLinkerExporter.java
Normal file
66
test/jdk/jdk/dynalink/TestGuardingDynamicLinkerExporter.java
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
import jdk.dynalink.CallSiteDescriptor;
|
||||
import jdk.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
|
||||
import jdk.dynalink.linker.LinkRequest;
|
||||
import jdk.dynalink.linker.LinkerServices;
|
||||
|
||||
/**
|
||||
* A trusted linker exporter (build file gives appropriate permission to the jar containing this class!).
|
||||
*/
|
||||
public final class TestGuardingDynamicLinkerExporter extends GuardingDynamicLinkerExporter {
|
||||
|
||||
private static final ThreadLocal<CallSiteDescriptor> lastDescriptor = new ThreadLocal<>();
|
||||
private static boolean enabled = false;
|
||||
|
||||
public static void enable() {
|
||||
reset(true);
|
||||
}
|
||||
|
||||
public static void disable() {
|
||||
reset(false);
|
||||
}
|
||||
public static boolean isLastCallSiteDescriptor(final CallSiteDescriptor desc) {
|
||||
return lastDescriptor.get() == desc;
|
||||
}
|
||||
|
||||
private static void reset(final boolean enable) {
|
||||
lastDescriptor.set(null);
|
||||
enabled = enable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GuardingDynamicLinker> get() {
|
||||
return List.of(((final LinkRequest linkRequest, final LinkerServices linkerServices) -> {
|
||||
if (enabled) {
|
||||
lastDescriptor.set(linkRequest.getCallSiteDescriptor());
|
||||
}
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
}
|
250
test/jdk/jdk/dynalink/TrustedDynamicLinkerFactoryTest.java
Normal file
250
test/jdk/jdk/dynalink/TrustedDynamicLinkerFactoryTest.java
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
import static jdk.dynalink.StandardNamespace.PROPERTY;
|
||||
import static jdk.dynalink.StandardOperation.GET;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.dynalink.CallSiteDescriptor;
|
||||
import jdk.dynalink.DynamicLinker;
|
||||
import jdk.dynalink.DynamicLinkerFactory;
|
||||
import jdk.dynalink.NoSuchDynamicMethodException;
|
||||
import jdk.dynalink.Operation;
|
||||
import jdk.dynalink.StandardNamespace;
|
||||
import jdk.dynalink.StandardOperation;
|
||||
import jdk.dynalink.beans.StaticClass;
|
||||
import jdk.dynalink.linker.GuardedInvocation;
|
||||
import jdk.dynalink.linker.LinkRequest;
|
||||
import jdk.dynalink.linker.LinkerServices;
|
||||
import jdk.dynalink.support.SimpleRelinkableCallSite;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @build TestGuardingDynamicLinkerExporter
|
||||
* @run testng/othervm/java.security.policy=trusted.security.policy TrustedDynamicLinkerFactoryTest
|
||||
*/
|
||||
public class TrustedDynamicLinkerFactoryTest {
|
||||
|
||||
private static final Operation GET_PROPERTY = GET.withNamespace(PROPERTY);
|
||||
|
||||
private static DynamicLinkerFactory newDynamicLinkerFactory(final boolean resetClassLoader) {
|
||||
final DynamicLinkerFactory factory = new DynamicLinkerFactory();
|
||||
if (resetClassLoader) {
|
||||
factory.setClassLoader(null);
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void callSiteCreationTest() {
|
||||
final DynamicLinkerFactory factory = newDynamicLinkerFactory(true);
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final StandardOperation[] operations = StandardOperation.values();
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class);
|
||||
for (final Operation op : operations) {
|
||||
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), op, mt)));
|
||||
Assert.assertNotNull(cs);
|
||||
Assert.assertEquals(cs.type(), mt);
|
||||
Assert.assertNotNull(cs.getTarget());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fallbackLinkerTest() {
|
||||
final DynamicLinkerFactory factory = newDynamicLinkerFactory(true);
|
||||
final Operation myOperation = new Operation() {
|
||||
};
|
||||
final boolean[] reachedFallback = { false };
|
||||
factory.setFallbackLinkers((final LinkRequest linkRequest, final LinkerServices linkerServices) -> {
|
||||
Assert.assertEquals(linkRequest.getCallSiteDescriptor().getOperation(), myOperation);
|
||||
reachedFallback[0] = true;
|
||||
return null;
|
||||
});
|
||||
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final MethodType mt = MethodType.methodType(Object.class);
|
||||
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), myOperation, mt)));
|
||||
|
||||
// linking the call site initially does not invoke the linkers!
|
||||
Assert.assertFalse(reachedFallback[0]);
|
||||
try {
|
||||
cs.getTarget().invoke();
|
||||
} catch (final NoSuchDynamicMethodException nsdm) {
|
||||
// we do expect NoSuchDynamicMethod!
|
||||
// because our dummy fallback linker returns null!
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException("should not reach here with: " + th);
|
||||
}
|
||||
|
||||
// check that the control reached fallback linker!
|
||||
Assert.assertTrue(reachedFallback[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void priorityLinkerTest() {
|
||||
final DynamicLinkerFactory factory = newDynamicLinkerFactory(true);
|
||||
final Operation myOperation = new Operation() {
|
||||
};
|
||||
final boolean[] reachedProrityLinker = { false };
|
||||
factory.setPrioritizedLinker((final LinkRequest linkRequest, final LinkerServices linkerServices) -> {
|
||||
Assert.assertEquals(linkRequest.getCallSiteDescriptor().getOperation(), myOperation);
|
||||
reachedProrityLinker[0] = true;
|
||||
return null;
|
||||
});
|
||||
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final MethodType mt = MethodType.methodType(Object.class);
|
||||
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), myOperation, mt)));
|
||||
|
||||
// linking the call site initially does not invoke the linkers!
|
||||
Assert.assertFalse(reachedProrityLinker[0]);
|
||||
try {
|
||||
cs.getTarget().invoke();
|
||||
} catch (final NoSuchDynamicMethodException nsdm) {
|
||||
// we do expect NoSuchDynamicMethod!
|
||||
// because our dummy priority linker returns null!
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException("should not reach here with: " + th);
|
||||
}
|
||||
|
||||
// check that the control reached fallback linker!
|
||||
Assert.assertTrue(reachedProrityLinker[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void priorityAndFallbackLinkerTest() {
|
||||
final DynamicLinkerFactory factory = newDynamicLinkerFactory(true);
|
||||
final Operation myOperation = new Operation() {
|
||||
};
|
||||
final int[] linkerReachCounter = { 0 };
|
||||
factory.setPrioritizedLinker((final LinkRequest linkRequest, final LinkerServices linkerServices) -> {
|
||||
Assert.assertEquals(linkRequest.getCallSiteDescriptor().getOperation(), myOperation);
|
||||
linkerReachCounter[0]++;
|
||||
return null;
|
||||
});
|
||||
factory.setFallbackLinkers((final LinkRequest linkRequest, final LinkerServices linkerServices) -> {
|
||||
Assert.assertEquals(linkRequest.getCallSiteDescriptor().getOperation(), myOperation);
|
||||
Assert.assertEquals(linkerReachCounter[0], 1);
|
||||
linkerReachCounter[0]++;
|
||||
return null;
|
||||
});
|
||||
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final MethodType mt = MethodType.methodType(Object.class);
|
||||
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), myOperation, mt)));
|
||||
|
||||
// linking the call site initially does not invoke the linkers!
|
||||
Assert.assertEquals(linkerReachCounter[0], 0);
|
||||
|
||||
try {
|
||||
cs.getTarget().invoke();
|
||||
} catch (final NoSuchDynamicMethodException nsdm) {
|
||||
// we do expect NoSuchDynamicMethod!
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException("should not reach here with: " + th);
|
||||
}
|
||||
|
||||
Assert.assertEquals(linkerReachCounter[0], 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prelinkTransformerTest() throws Throwable {
|
||||
final DynamicLinkerFactory factory = newDynamicLinkerFactory(true);
|
||||
final boolean[] reachedPrelinkTransformer = { false };
|
||||
|
||||
factory.setPrelinkTransformer((final GuardedInvocation inv, final LinkRequest linkRequest, final LinkerServices linkerServices) -> {
|
||||
reachedPrelinkTransformer[0] = true;
|
||||
// just identity transformer!
|
||||
return inv;
|
||||
});
|
||||
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), GET_PROPERTY, mt)));
|
||||
Assert.assertFalse(reachedPrelinkTransformer[0]);
|
||||
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
|
||||
Assert.assertTrue(reachedPrelinkTransformer[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void internalObjectsFilterTest() throws Throwable {
|
||||
final DynamicLinkerFactory factory = newDynamicLinkerFactory(true);
|
||||
final boolean[] reachedInternalObjectsFilter = { false };
|
||||
|
||||
factory.setInternalObjectsFilter((final MethodHandle mh) -> {
|
||||
reachedInternalObjectsFilter[0] = true;
|
||||
return mh;
|
||||
});
|
||||
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
|
||||
MethodHandles.publicLookup(), GET_PROPERTY, mt)));
|
||||
Assert.assertFalse(reachedInternalObjectsFilter[0]);
|
||||
Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
|
||||
Assert.assertTrue(reachedInternalObjectsFilter[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoadedLinkerTest() {
|
||||
testAutoLoadedLinkerInvoked(new Object(), "toString");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoLoadedLinkerSeesStaticMethod() {
|
||||
testAutoLoadedLinkerInvoked(StaticClass.forClass(System.class), "currentTimeMillis");
|
||||
}
|
||||
|
||||
private static void testAutoLoadedLinkerInvoked(final Object target, final String methodName) {
|
||||
final DynamicLinkerFactory factory = newDynamicLinkerFactory(false);
|
||||
final DynamicLinker linker = factory.createLinker();
|
||||
|
||||
final MethodType mt = MethodType.methodType(Object.class, Object.class);
|
||||
final CallSiteDescriptor testDescriptor = new CallSiteDescriptor(MethodHandles.publicLookup(),
|
||||
GET.withNamespace(StandardNamespace.METHOD).named(methodName), mt);
|
||||
final CallSite cs = linker.link(new SimpleRelinkableCallSite(testDescriptor));
|
||||
|
||||
TestGuardingDynamicLinkerExporter.enable();
|
||||
try {
|
||||
cs.getTarget().invoke(target);
|
||||
// The linker was loaded and it observed our invocation
|
||||
Assert.assertTrue(TestGuardingDynamicLinkerExporter.isLastCallSiteDescriptor(testDescriptor));
|
||||
} catch (final Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
} finally {
|
||||
TestGuardingDynamicLinkerExporter.disable();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
50
test/jdk/jdk/dynalink/UntrustedDynamicLinkerFactoryTest.java
Normal file
50
test/jdk/jdk/dynalink/UntrustedDynamicLinkerFactoryTest.java
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
import java.util.List;
|
||||
import java.util.ServiceConfigurationError;
|
||||
import jdk.dynalink.DynamicLinkerFactory;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @build TestGuardingDynamicLinkerExporter
|
||||
* @run testng/othervm/java.security.policy=untrusted.security.policy UntrustedDynamicLinkerFactoryTest
|
||||
*/
|
||||
public class UntrustedDynamicLinkerFactoryTest {
|
||||
@Test
|
||||
public void autoLoadedLinkerNegativeTest() {
|
||||
final DynamicLinkerFactory factory = new DynamicLinkerFactory();
|
||||
factory.createLinker();
|
||||
// expect one error as we have one untrusted linker exporter in META-INF/services
|
||||
final List<ServiceConfigurationError> autoLoadingErrors = factory.getAutoLoadingErrors();
|
||||
// single error ...
|
||||
Assert.assertEquals(autoLoadingErrors.size(), 1);
|
||||
autoLoadingErrors.get(0).printStackTrace();
|
||||
final Throwable cause = autoLoadingErrors.get(0).getCause();
|
||||
// .. due to permission check..
|
||||
Assert.assertTrue(cause.toString().contains("dynalink.exportLinkersAutomatically"));
|
||||
}
|
||||
}
|
7
test/jdk/jdk/dynalink/trusted.security.policy
Normal file
7
test/jdk/jdk/dynalink/trusted.security.policy
Normal file
@ -0,0 +1,7 @@
|
||||
grant {
|
||||
permission java.io.FilePermission "${user.home}/-", "read";
|
||||
};
|
||||
|
||||
grant codeBase "file:${test.classes}/-" {
|
||||
permission java.lang.RuntimePermission "dynalink.exportLinkersAutomatically";
|
||||
};
|
3
test/jdk/jdk/dynalink/untrusted.security.policy
Normal file
3
test/jdk/jdk/dynalink/untrusted.security.policy
Normal file
@ -0,0 +1,3 @@
|
||||
grant {
|
||||
permission java.io.FilePermission "${user.home}/-", "read";
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user