Add regression test for b/36989421
There was an old bug in some versions of art/dalvik that caused
InvokeNonVirtual* JNI functions to call the wrong methods. Add a test
that the right behavior is done.
No functional change required. The behavior seems to have been fixed
at some point.
Test: ./test.py --host
Bug: 36989421
Change-Id: Iddd518c780f01b680a4bf832a7f8ada07f19289a
diff --git a/test/179-nonvirtual-jni/expected.txt b/test/179-nonvirtual-jni/expected.txt
new file mode 100644
index 0000000..7b603b1
--- /dev/null
+++ b/test/179-nonvirtual-jni/expected.txt
@@ -0,0 +1,9 @@
+JNI_OnLoad called
+Call lookup: Base, caller: Base, Obj: Base
+Hello from Base
+Call lookup: Base, caller: Base, Obj: Ext
+Hello from Base
+Call lookup: Base, caller: Ext, Obj: Ext
+Hello from Base
+Call lookup: Ext, caller: Ext, Obj: Ext
+Hello from Ext
diff --git a/test/179-nonvirtual-jni/info.txt b/test/179-nonvirtual-jni/info.txt
new file mode 100644
index 0000000..528d3a4
--- /dev/null
+++ b/test/179-nonvirtual-jni/info.txt
@@ -0,0 +1 @@
+Ensure that calls to InvokeNonVirtual resolve correctly
diff --git a/test/179-nonvirtual-jni/nonvirtual-call.cc b/test/179-nonvirtual-jni/nonvirtual-call.cc
new file mode 100644
index 0000000..ef6c6c8
--- /dev/null
+++ b/test/179-nonvirtual-jni/nonvirtual-call.cc
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include <jni.h>
+#include <nativehelper/scoped_local_ref.h>
+#include <pthread.h>
+
+#include <android-base/logging.h>
+
+namespace art {
+
+extern "C" JNIEXPORT void JNICALL Java_Main_callSayHiMethodNonvirtualWith(
+ JNIEnv* env, jclass, jclass lookup, jclass caller, jobject recv) {
+ jmethodID meth = env->GetMethodID(lookup, "sayHi", "()V");
+ env->CallNonvirtualVoidMethod(recv, caller, meth);
+}
+
+} // namespace art
diff --git a/test/179-nonvirtual-jni/src/Main.java b/test/179-nonvirtual-jni/src/Main.java
new file mode 100644
index 0000000..e809d41
--- /dev/null
+++ b/test/179-nonvirtual-jni/src/Main.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+public class Main {
+ public static class Base {
+ public void sayHi() {
+ System.out.println("Hello from Base");
+ }
+ }
+ public static class Ext extends Base{
+ public void sayHi() {
+ System.out.println("Hello from Ext");
+ }
+ }
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+ try {
+ System.out.println("Call lookup: Base, caller: Base, Obj: Base");
+ callSayHiMethodNonvirtualWith(Base.class, Base.class, new Base());
+ } catch (Exception e) {
+ System.out.println("Caught exception " + e);
+ }
+ try {
+ System.out.println("Call lookup: Base, caller: Base, Obj: Ext");
+ callSayHiMethodNonvirtualWith(Base.class, Base.class, new Ext());
+ } catch (Exception e) {
+ System.out.println("Caught exception " + e);
+ }
+ try {
+ System.out.println("Call lookup: Base, caller: Ext, Obj: Ext");
+ callSayHiMethodNonvirtualWith(Base.class, Ext.class, new Ext());
+ } catch (Exception e) {
+ System.out.println("Caught exception " + e);
+ }
+ try {
+ System.out.println("Call lookup: Ext, caller: Ext, Obj: Ext");
+ callSayHiMethodNonvirtualWith(Ext.class, Ext.class, new Ext());
+ } catch (Exception e) {
+ System.out.println("Caught exception " + e);
+ }
+ }
+
+ private static native void callSayHiMethodNonvirtualWith(Class<?> lookup, Class<?> caller, Object recv);
+}
diff --git a/test/Android.bp b/test/Android.bp
index 769f39f..b8cf417 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -566,6 +566,7 @@
"172-app-image-twice/debug_print_class.cc",
"177-visibly-initialized-deadlock/visibly_initialized.cc",
"178-app-image-native-method/native_methods.cc",
+ "179-nonvirtual-jni/nonvirtual-call.cc",
"1945-proxy-method-arguments/get_args.cc",
"203-multi-checkpoint/multi_checkpoint.cc",
"305-other-fault-handler/fault_handler.cc",