summaryrefslogtreecommitdiff
path: root/test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java')
-rw-r--r--test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java270
1 files changed, 270 insertions, 0 deletions
diff --git a/test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java b/test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java
new file mode 100644
index 0000000000..569bff61b2
--- /dev/null
+++ b/test/2277-methodhandle-invokeexact/src/AbstractInvokeExactTest.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2024 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 java.lang.invoke.MethodHandle;
+import java.lang.invoke.WrongMethodTypeException;
+import java.util.Objects;
+
+public abstract class AbstractInvokeExactTest {
+
+ public static String STATUS = "";
+
+ public final void runAll() throws Throwable {
+ STATUS = "";
+ Multi.$noinline$testMHFromMain(optionalGet());
+ $noinline$privateMethods();
+ $noinline$testNoArgsCalls();
+ $noinline$nullchecks();
+ $noinline$testWithArgs();
+ $noinline$interfaceChecks();
+ $noinline$abstractClass();
+ }
+
+ // There is no privateLookupIn for const-method-handle.
+ abstract void $noinline$privateMethods() throws Throwable;
+
+ private void $noinline$testNoArgsCalls() throws Throwable {
+ voidMethod().invokeExact(new A());
+ assertEquals("A.voidMethod", STATUS);
+
+ int returnedInt = (int) returnInt().invokeExact(new A());
+ assertEquals(42, returnedInt);
+
+ double returnedDouble = (double) returnDouble().invokeExact(new A());
+ assertEquals(42.0d, returnedDouble);
+ try {
+ interfaceDefaultMethod().invokeExact(new A());
+ unreachable("MethodHandle's type is (Main$I)V, but callsite is (Main$A)V");
+ } catch (WrongMethodTypeException expected) {}
+
+ interfaceDefaultMethod().invokeExact((I) new A());
+ assertEquals("I.defaultMethod", STATUS);
+
+ overwrittenInterfaceDefaultMethod().invokeExact((I) new A());
+ assertEquals("A.overrideMe", STATUS);
+
+
+ try {
+ exceptionThrowingMethod().invokeExact(new A());
+ unreachable("Target method always throws");
+ } catch (MyRuntimeException expected) {
+ assertEquals("A.throwException", STATUS);
+ }
+
+ try {
+ returnInt().invokeExact(new A());
+ unreachable("MethodHandle's type is (Main$A)I, but callsite type is (Main$A)V");
+ } catch (WrongMethodTypeException expected) {}
+
+ String returnedString = (String) staticMethod().invokeExact(new A());
+ assertEquals("staticMethod", returnedString);
+ }
+
+ private void $noinline$nullchecks() throws Throwable {
+ try {
+ voidMethod().invokeExact((A) null);
+ unreachable("Receiver is null, should throw NPE");
+ } catch (NullPointerException expected) {}
+
+ try {
+ voidMethod().invokeExact((Main) null);
+ unreachable("Should throw WMTE: input is of wrong type");
+ } catch (WrongMethodTypeException expected) {}
+
+ try {
+ interfaceDefaultMethod().invokeExact((I) null);
+ unreachable("Receiver is null, should throw NPE");
+ } catch (NullPointerException expected) {}
+
+ try {
+ interfaceDefaultMethod().invokeExact((A) null);
+ unreachable("Should throw WMTE: input is of wrong type");
+ } catch (WrongMethodTypeException expected) {}
+
+ try {
+ MethodHandle mh = $noinline$nullMethodHandle();
+ mh.invokeExact();
+ unreachable("MethodHandle object is null, should throw NPE");
+ } catch (NullPointerException expected) {}
+ }
+
+ private static MethodHandle $noinline$nullMethodHandle() {
+ return null;
+ }
+
+ private void $noinline$testWithArgs() throws Throwable {
+ int sum = (int) sumI().invokeExact(new Sums(), 1);
+ assertEquals(1, sum);
+
+ sum = (int) sum2I().invokeExact(new Sums(), 1, 2);
+ assertEquals(3, sum);
+
+ sum = (int) sum3I().invokeExact(new Sums(), 1, 2, 3);
+ assertEquals(6, sum);
+
+ sum = (int) sum4I().invokeExact(new Sums(), 1, 2, 3, 4);
+ assertEquals(10, sum);
+
+ sum = (int) sum5I().invokeExact(new Sums(), 1, 2, 3, 4, 5);
+ assertEquals(15, sum);
+
+ sum = (int) sum6I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6);
+ assertEquals(21, sum);
+
+ sum = (int) sum7I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7);
+ assertEquals(28, sum);
+
+ sum = (int) sum8I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7, 8);
+ assertEquals(36, sum);
+
+ sum = (int) sum9I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ assertEquals(45, sum);
+
+ sum = (int) sum10I().invokeExact(new Sums(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ assertEquals(55, sum);
+
+ long lsum = (long) sumIJ().invokeExact(new Sums(), 1, 2L);
+ assertEquals(3L, lsum);
+
+ lsum = (long) sum2IJ().invokeExact(new Sums(), 1, 2L, 3, 4L);
+ assertEquals(10L, lsum);
+
+ lsum = (long) sum3IJ().invokeExact(new Sums(), 1, 2L, 3, 4L, 5, 6L);
+ assertEquals(21L, lsum);
+
+ lsum = (long) sum4IJ().invokeExact(new Sums(), 1, 2L, 3, 4L, 5, 6L, 7, 8L);
+ assertEquals(36L, lsum);
+
+ lsum = (long) sum5IJ().invokeExact(new Sums(), 1, 2L, 3, 4L, 5, 6L, 7, 8L, 9, 10L);
+ assertEquals(55L, lsum);
+ }
+
+ private void $noinline$interfaceChecks() throws Throwable {
+ FooBarImpl instance = new FooBarImpl();
+
+ String result = null;
+ result = (String) fooNonDefault().invokeExact((Foo) instance);
+ assertEquals("FooBarImpl.nonDefault", result);
+
+ result = (String) fooBarImplNonDefault().invokeExact(instance);
+ assertEquals("FooBarImpl.nonDefault", result);
+
+ result = (String) barDefault().invokeExact((Bar) instance);
+ assertEquals("Bar.defaultToOverride", result);
+
+ result = (String) fooDefault().invokeExact((Foo) instance);
+ assertEquals("Bar.defaultToOverride", result);
+
+ result = (String) fooBarImplDefault().invokeExact(instance);
+ assertEquals("Bar.defaultToOverride", result);
+
+ result = (String) fooNonOverriddenDefault().invokeExact((Foo) instance);
+ assertEquals("Foo.nonOverriddenDefault", result);
+
+ result = (String) barNonOverriddenDefault().invokeExact((Bar) instance);
+ assertEquals("Foo.nonOverriddenDefault", result);
+ }
+
+ private void $noinline$abstractClass() throws Throwable {
+ FooBarImpl instance = new FooBarImpl();
+
+ String result = null;
+ result = (String) fooBarDefinedInAbstract().invokeExact((FooBar) instance);
+ assertEquals("FooBar.definedInAbstract", result);
+
+ result = (String) fooBarImplDefinedInAbstract().invokeExact(instance);
+ assertEquals("FooBar.definedInAbstract", result);
+
+ FooBar fooBar = new FooBar() {
+ @Override
+ public String nonDefault() {
+ return "anonymous.nonDefault";
+ }
+ };
+
+ result = (String) fooBarDefinedInAbstract().invokeExact(fooBar);
+ assertEquals("FooBar.definedInAbstract", result);
+
+ result = (String) fooBarNonDefault().invokeExact(fooBar);
+ assertEquals("anonymous.nonDefault", result);
+ }
+
+ static void assertEquals(Object expected, Object actual) {
+ if (!Objects.equals(expected, actual)) {
+ throw new AssertionError("Expected: " + expected + ", got: " + actual);
+ }
+ }
+
+ private static void assertEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected: " + expected + ", got: " + actual);
+ }
+ }
+
+ private static void assertEquals(long expected, long actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected: " + expected + ", got: " + actual);
+ }
+ }
+
+ private static void assertEquals(double expected, double actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected: " + expected + ", got: " + actual);
+ }
+ }
+
+ static void unreachable(String msg) {
+ throw new AssertionError("Unexpectedly reached this point, but shouldn't: " + msg);
+ }
+
+ public abstract MethodHandle optionalGet();
+
+ public abstract MethodHandle voidMethod();
+ public abstract MethodHandle returnInt();
+ public abstract MethodHandle returnDouble();
+ public abstract MethodHandle interfaceDefaultMethod();
+ public abstract MethodHandle overwrittenInterfaceDefaultMethod();
+ public abstract MethodHandle exceptionThrowingMethod();
+ public abstract MethodHandle staticMethod();
+
+ public abstract MethodHandle sumI();
+ public abstract MethodHandle sum2I();
+ public abstract MethodHandle sum3I();
+ public abstract MethodHandle sum4I();
+ public abstract MethodHandle sum5I();
+ public abstract MethodHandle sum6I();
+ public abstract MethodHandle sum7I();
+ public abstract MethodHandle sum8I();
+ public abstract MethodHandle sum9I();
+ public abstract MethodHandle sum10I();
+ public abstract MethodHandle sumIJ();
+ public abstract MethodHandle sum2IJ();
+ public abstract MethodHandle sum3IJ();
+ public abstract MethodHandle sum4IJ();
+ public abstract MethodHandle sum5IJ();
+
+ public abstract MethodHandle fooNonDefault();
+ public abstract MethodHandle fooBarImplNonDefault();
+ public abstract MethodHandle barDefault();
+ public abstract MethodHandle fooDefault();
+ public abstract MethodHandle fooBarImplDefault();
+ public abstract MethodHandle fooNonOverriddenDefault();
+ public abstract MethodHandle barNonOverriddenDefault();
+
+ public abstract MethodHandle fooBarDefinedInAbstract();
+ public abstract MethodHandle fooBarImplDefinedInAbstract();
+ public abstract MethodHandle fooBarNonDefault();
+}