blob: 25d8b59eaa42524b8f6f08b0ed774760cc4b227b [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import annotations.BootstrapMethod;
import annotations.CalledByIndy;
import annotations.Constant;
import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.WrongMethodTypeException;
public class TestBadBootstrapArguments extends TestBase {
private static CallSite bsm(
MethodHandles.Lookup lookup,
String methodName,
MethodType methodType,
int extraInt,
String extraString)
throws Throwable {
System.out.print("bsm(");
System.out.print(lookup.lookupClass());
System.out.print(", ");
System.out.print(methodName);
System.out.print(", ");
System.out.print(methodType);
System.out.print(", ");
System.out.print(extraInt);
System.out.print(", ");
System.out.print(extraString);
System.out.println(")");
MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType);
return new ConstantCallSite(mh);
}
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsm",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
int.class,
String.class
}
),
fieldOrMethodName = "happy",
constantArgumentsForBootstrapMethod = {
@Constant(intValue = -1),
@Constant(stringValue = "very")
}
)
private static void invokeHappy() {
assertNotReached();
}
private static void happy() {
System.out.println("happy");
}
// BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod)
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsm",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
int.class,
double.class
}
),
fieldOrMethodName = "wrongParameterTypes",
constantArgumentsForBootstrapMethod = {
@Constant(intValue = -1),
@Constant(stringValue = "very")
}
)
private static void invokeWrongParameterTypes() throws NoSuchMethodError {
assertNotReached();
}
private static void wrongParameterTypes() {
System.out.println("wrongParameterTypes");
}
// BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod)
// (missing constantArgumentTypes))
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsm",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
int.class,
double.class
}
),
fieldOrMethodName = "missingParameterTypes",
constantArgumentsForBootstrapMethod = {}
)
private static void invokeMissingParameterTypes() throws NoSuchMethodError {
assertNotReached();
}
private static void missingParameterTypes() {
System.out.println("missingParameterTypes");
}
// BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod):
// extra constant present
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsm",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
int.class,
String.class
}
),
fieldOrMethodName = "extraArguments",
constantArgumentsForBootstrapMethod = {
@Constant(intValue = 1),
@Constant(stringValue = "2"),
@Constant(intValue = 3)
}
)
private static void invokeExtraArguments() {
assertNotReached();
}
private static void extraArguments() {
System.out.println("extraArguments");
}
// constantArgumentTypes do not correspond to expected parameter types
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsm",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
int.class,
String.class
}
),
fieldOrMethodName = "wrongArguments",
constantArgumentsForBootstrapMethod = {
@Constant(stringValue = "1"),
@Constant(doubleValue = Math.PI)
}
)
private static void invokeWrongArguments() {
assertNotReached();
}
private static void wrongArguments() {
System.out.println("wrongArguments");
}
// constantArgumentTypes do not correspond to expected parameter types
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsm",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
int.class,
String.class
}
),
fieldOrMethodName = "wrongArgumentsAgain",
constantArgumentsForBootstrapMethod = {
@Constant(doubleValue = Math.PI),
@Constant(stringValue = "pie")
}
)
private static void invokeWrongArgumentsAgain() {
assertNotReached();
}
private static void wrongArgumentsAgain() {
System.out.println("wrongArgumentsAgain");
}
// Primitive argument types not supported {Z, B, C, S}.
private static CallSite bsmZBCS(
MethodHandles.Lookup lookup,
String methodName,
MethodType methodType,
boolean extraArg0,
byte extraArg1,
char extraArg2,
short extraArg3)
throws Throwable {
assertNotReached();
return null;
}
// Arguments are narrower than supported.
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsmZBCS",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
boolean.class,
byte.class,
char.class,
short.class
}
),
fieldOrMethodName = "narrowArguments",
constantArgumentsForBootstrapMethod = {
@Constant(booleanValue = true),
@Constant(byteValue = Byte.MAX_VALUE),
@Constant(charValue = 'A'),
@Constant(shortValue = Short.MIN_VALUE)
}
)
private static void invokeNarrowArguments() {
assertNotReached();
}
private static void narrowArguments() {
assertNotReached();
}
private static CallSite bsmDJ(
MethodHandles.Lookup lookup,
String methodName,
MethodType methodType,
double extraArg0,
long extraArg1)
throws Throwable {
System.out.print("bsmDJ(..., ");
System.out.print(extraArg0);
System.out.print(", ");
System.out.print(extraArg1);
System.out.println(")");
MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType);
return new ConstantCallSite(mh);
}
// Arguments need widening to parameter types.
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsmDJ",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
double.class,
long.class
}
),
fieldOrMethodName = "wideningArguments",
constantArgumentsForBootstrapMethod = {
@Constant(doubleValue = Double.MAX_VALUE),
@Constant(intValue = Integer.MAX_VALUE)
}
)
private static void invokeWideningArguments() {
assertNotReached();
}
private static void wideningArguments() {
System.out.println("wideningArguments");
}
private static CallSite bsmDoubleLong(
MethodHandles.Lookup lookup,
String methodName,
MethodType methodType,
Double extraArg0,
Long extraArg1)
throws Throwable {
System.out.print("bsmDoubleLong(..., ");
System.out.print(extraArg0);
System.out.print(", ");
System.out.print(extraArg1);
System.out.println(")");
MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType);
return new ConstantCallSite(mh);
}
// Arguments need boxing to parameter types
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsmDoubleLong",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
Double.class,
Long.class
}
),
fieldOrMethodName = "boxingArguments",
constantArgumentsForBootstrapMethod = {
@Constant(doubleValue = Double.MAX_VALUE),
@Constant(longValue = Long.MAX_VALUE)
}
)
private static void invokeBoxingArguments() {
assertNotReached();
}
private static void boxingArguments() {
System.out.println("boxingArguments");
}
// Arguments need widening and boxing to parameter types
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsmDoubleLong",
parameterTypes = {
MethodHandles.Lookup.class,
String.class,
MethodType.class,
Double.class,
Long.class
}
),
fieldOrMethodName = "wideningBoxingArguments",
constantArgumentsForBootstrapMethod = {
@Constant(floatValue = Float.MAX_VALUE),
@Constant(longValue = Integer.MAX_VALUE)
}
)
private static void invokeWideningBoxingArguments() {
assertNotReached();
}
private static void wideningBoxingArguments() {
System.out.println("wideningBoxingArguments");
}
static void bsmReturningVoid(MethodHandles.Lookup lookup, String name, MethodType type) {
System.out.println("bsm returning void value.");
}
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsmReturningVoid",
parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
returnType = void.class
),
fieldOrMethodName = "voidReturnType"
)
private static void invokeVoidReturnType() {
assertNotReached();
}
private static void voidReturnType() {
assertNotReached();
}
static Object bsmReturningObject(MethodHandles.Lookup lookup, String name, MethodType type) {
System.out.println("bsm returning Object value.");
return new Object();
}
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsmReturningObject",
parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
returnType = Object.class
),
fieldOrMethodName = "ObjectReturnType"
)
private static void invokeObjectReturnType() {
assertNotReached();
}
private static void objectReturnType() {
assertNotReached();
}
static Integer bsmReturningInteger(MethodHandles.Lookup lookup, String name, MethodType type) {
System.out.println("bsm returning Integer value.");
return Integer.valueOf(3);
}
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsmReturningInteger",
parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
returnType = Integer.class
),
fieldOrMethodName = "integerReturnType"
)
private static void invokeIntegerReturnType() {
assertNotReached();
}
private static void integerReturnType() {
assertNotReached();
}
static class TestersConstantCallSite extends ConstantCallSite {
public TestersConstantCallSite(MethodHandle mh) {
super(mh);
}
}
static TestersConstantCallSite bsmReturningTestersConstantCallsite(
MethodHandles.Lookup lookup, String name, MethodType type) throws Throwable {
return new TestersConstantCallSite(lookup.findStatic(lookup.lookupClass(), name, type));
}
@CalledByIndy(
bootstrapMethod =
@BootstrapMethod(
enclosingType = TestBadBootstrapArguments.class,
name = "bsmReturningTestersConstantCallsite",
parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
returnType = TestersConstantCallSite.class
),
fieldOrMethodName = "sayHello"
)
private static void invokeViaCustomCallSiteClass() {
assertNotReached();
}
private static void sayHello() {
System.out.println("Hello!");
}
static void test() {
System.out.println("TestBadBootstrapArguments");
invokeHappy();
try {
invokeWrongParameterTypes();
assertNotReached();
} catch (NoSuchMethodError expected) {
System.out.print("invokeWrongParameterTypes => ");
System.out.println(expected.getClass());
}
try {
invokeMissingParameterTypes();
assertNotReached();
} catch (NoSuchMethodError expected) {
System.out.print("invokeMissingParameterTypes => ");
System.out.println(expected.getClass());
}
try {
invokeExtraArguments();
assertNotReached();
} catch (BootstrapMethodError expected) {
assertEquals(WrongMethodTypeException.class, expected.getCause().getClass());
System.out.print("invokeExtraArguments => ");
System.out.print(expected.getClass());
System.out.print(" => ");
System.out.println(expected.getCause().getClass());
}
try {
invokeWrongArguments();
assertNotReached();
} catch (BootstrapMethodError expected) {
assertEquals(ClassCastException.class, expected.getCause().getClass());
System.out.print("invokeWrongArguments => ");
System.out.print(expected.getClass());
System.out.print(" => ");
System.out.println(expected.getCause().getClass());
}
try {
invokeWrongArguments();
assertNotReached();
} catch (BootstrapMethodError expected) {
assertEquals(ClassCastException.class, expected.getCause().getClass());
System.out.print("invokeWrongArguments => ");
System.out.print(expected.getClass());
System.out.print(" => ");
System.out.println(expected.getCause().getClass());
}
try {
invokeWrongArgumentsAgain();
assertNotReached();
} catch (BootstrapMethodError expected) {
assertEquals(ClassCastException.class, expected.getCause().getClass());
System.out.print("invokeWrongArgumentsAgain => ");
System.out.print(expected.getClass());
System.out.print(" => ");
System.out.println(expected.getCause().getClass());
}
try {
invokeNarrowArguments();
assertNotReached();
} catch (BootstrapMethodError expected) {
assertEquals(ClassCastException.class, expected.getCause().getClass());
System.out.print("invokeNarrowArguments => ");
System.out.print(expected.getClass());
System.out.print(" => ");
System.out.println(expected.getCause().getClass());
}
invokeWideningArguments();
invokeBoxingArguments();
try {
invokeWideningBoxingArguments();
assertNotReached();
} catch (BootstrapMethodError expected) {
System.out.print("invokeWideningBoxingArguments => ");
System.out.print(expected.getClass());
System.out.print(" => ");
System.out.println(expected.getCause().getClass());
}
try {
invokeVoidReturnType();
assertNotReached();
} catch (BootstrapMethodError expected) {
System.out.print("invokeVoidReturnType() => ");
System.out.print(expected.getClass());
System.out.print(" => ");
System.out.println(expected.getCause().getClass());
}
try {
invokeObjectReturnType();
assertNotReached();
} catch (BootstrapMethodError expected) {
System.out.print("invokeObjectReturnType() => ");
System.out.print(expected.getClass());
System.out.print(" => ");
System.out.println(expected.getCause().getClass());
}
try {
invokeIntegerReturnType();
assertNotReached();
} catch (BootstrapMethodError expected) {
System.out.print("invokeIntegerReturnType() => ");
System.out.print(expected.getClass());
System.out.print(" => ");
System.out.println(expected.getCause().getClass());
}
invokeViaCustomCallSiteClass();
}
}