Implement various JNI internals. Fix off by 1 bug.
Make GetMethodID and GetStaticMethodID throw NoSuchMethodError. Add
simple unit tests. Implement RegisterNatives.
Fix bug that CreateArgArray doesn't pass the last argument correctly.
Change-Id: I5b87ffdbb72a7ef75147a002560b8c47e7af35f4
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index 569dfda..04b3225 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -57,6 +57,117 @@
EXPECT_CLASS_NOT_FOUND("K");
}
+TEST_F(JniInternalTest, GetMethodID) {
+ jclass jlobject = env_->FindClass("java/lang/Object");
+ jclass jlstring = env_->FindClass("java/lang/String");
+ jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
+
+ // Sanity check that no exceptions are pending
+ EXPECT_FALSE(env_->ExceptionCheck());
+
+ // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
+ // a pending exception
+ jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
+ EXPECT_EQ(static_cast<jmethodID>(NULL), method);
+ EXPECT_TRUE(env_->ExceptionCheck());
+ jthrowable exception = env_->ExceptionOccurred();
+ EXPECT_NE(static_cast<jthrowable>(NULL), exception);
+ EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
+ env_->ExceptionClear();
+
+ // Check that java.lang.Object.equals() does exist
+#if defined(__arm__)
+ method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
+ EXPECT_NE(static_cast<jmethodID>(NULL), method);
+ EXPECT_FALSE(env_->ExceptionCheck());
+#endif
+
+ // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
+ // method is static
+ method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
+ EXPECT_EQ(static_cast<jmethodID>(NULL), method);
+ EXPECT_TRUE(env_->ExceptionCheck());
+ exception = env_->ExceptionOccurred();
+ EXPECT_NE(static_cast<jthrowable>(NULL), exception);
+ EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
+ env_->ExceptionClear();
+}
+
+TEST_F(JniInternalTest, GetStaticMethodID) {
+ jclass jlobject = env_->FindClass("java/lang/Object");
+ jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
+
+ // Sanity check that no exceptions are pending
+ EXPECT_FALSE(env_->ExceptionCheck());
+
+ // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
+ // a pending exception
+ jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
+ EXPECT_EQ(static_cast<jmethodID>(NULL), method);
+ EXPECT_TRUE(env_->ExceptionCheck());
+ jthrowable exception = env_->ExceptionOccurred();
+ EXPECT_NE(static_cast<jthrowable>(NULL), exception);
+ EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
+ env_->ExceptionClear();
+
+ // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
+ // the method is not static
+ method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
+ EXPECT_EQ(static_cast<jmethodID>(NULL), method);
+ EXPECT_TRUE(env_->ExceptionCheck());
+ exception = env_->ExceptionOccurred();
+ EXPECT_NE(static_cast<jthrowable>(NULL), exception);
+ EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
+ env_->ExceptionClear();
+
+ // Check that java.lang.String.valueOf(int) does exist
+#if defined(__arm__)
+ jclass jlstring = env_->FindClass("java/lang/String");
+ method = env_->GetStaticMethodID(jlstring, "valueOf",
+ "(I)Ljava/lang/String;");
+ EXPECT_NE(static_cast<jmethodID>(NULL), method);
+ EXPECT_FALSE(env_->ExceptionCheck());
+#endif
+}
+
+TEST_F(JniInternalTest, RegisterNatives) {
+ jclass jlobject = env_->FindClass("java/lang/Object");
+ jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
+
+ // Sanity check that no exceptions are pending
+ EXPECT_FALSE(env_->ExceptionCheck());
+
+ // Check that registering to a non-existent java.lang.Object.foo() causes a
+ // NoSuchMethodError
+ {
+ JNINativeMethod methods[] = {{"foo", "()V", NULL}};
+ env_->RegisterNatives(jlobject, methods, 1);
+ }
+ EXPECT_TRUE(env_->ExceptionCheck());
+ jthrowable exception = env_->ExceptionOccurred();
+ EXPECT_NE(static_cast<jthrowable>(NULL), exception);
+ EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
+ env_->ExceptionClear();
+
+ // Check that registering non-native methods causes a NoSuchMethodError
+ {
+ JNINativeMethod methods[] = {{"equals", "(Ljava/lang/Object;)Z", NULL}};
+ env_->RegisterNatives(jlobject, methods, 1);
+ }
+ EXPECT_TRUE(env_->ExceptionCheck());
+ exception = env_->ExceptionOccurred();
+ EXPECT_NE(static_cast<jthrowable>(NULL), exception);
+ EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
+ env_->ExceptionClear();
+
+ // Check that registering native methods is successful
+ {
+ JNINativeMethod methods[] = {{"hashCode", "()I", NULL}};
+ env_->RegisterNatives(jlobject, methods, 1);
+ }
+ EXPECT_FALSE(env_->ExceptionCheck());
+}
+
TEST_F(JniInternalTest, NewPrimitiveArray) {
// TODO: death tests for negative array sizes.