Add some missing JNI string functions, GetObjectArrayElement, and all the primitive array region functions.
This also pulls the UTF-8/UTF-16 functions out of class String.
Change-Id: I75936b84fd619c9cf91f6e6a6037488220b05781
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index ee4f2b1..53b8334 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -15,8 +15,11 @@
virtual void SetUp() {
CommonTest::SetUp();
env_ = Thread::Current()->GetJniEnv();
+ aioobe_ = env_->FindClass("java/lang/ArrayIndexOutOfBoundsException");
+ CHECK(aioobe_ != NULL);
}
JNIEnv* env_;
+ jclass aioobe_;
};
TEST_F(JniInternalTest, AllocObject) {
@@ -260,35 +263,69 @@
EXPECT_FALSE(env_->ExceptionCheck());
}
-#define EXPECT_PRIMITIVE_ARRAY(fn, size, expected_class_descriptor) \
- do { \
- jarray a = env_->fn(size); \
- EXPECT_TRUE(a != NULL); \
- EXPECT_TRUE(env_->IsInstanceOf(a, \
- env_->FindClass(expected_class_descriptor))); \
- EXPECT_EQ(size, env_->GetArrayLength(a)); \
- } while (false)
+#define EXPECT_PRIMITIVE_ARRAY(new_fn, get_region_fn, set_region_fn, scalar_type, expected_class_descriptor) \
+ jsize size = 4; \
+ /* Allocate an array and check it has the right type and length. */ \
+ scalar_type ## Array a = env_->new_fn(size); \
+ EXPECT_TRUE(a != NULL); \
+ EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
+ EXPECT_EQ(size, env_->GetArrayLength(a)); \
+ /* AIOOBE for negative start offset. */ \
+ env_->get_region_fn(a, -1, 1, NULL); \
+ EXPECT_EXCEPTION(aioobe_); \
+ env_->set_region_fn(a, -1, 1, NULL); \
+ EXPECT_EXCEPTION(aioobe_); \
+ /* AIOOBE for negative length. */ \
+ env_->get_region_fn(a, 0, -1, NULL); \
+ EXPECT_EXCEPTION(aioobe_); \
+ env_->set_region_fn(a, 0, -1, NULL); \
+ EXPECT_EXCEPTION(aioobe_); \
+ /* AIOOBE for buffer overrun. */ \
+ env_->get_region_fn(a, size - 1, size, NULL); \
+ EXPECT_EXCEPTION(aioobe_); \
+ env_->set_region_fn(a, size - 1, size, NULL); \
+ EXPECT_EXCEPTION(aioobe_); \
+ /* Prepare a couple of buffers. */ \
+ scalar_type src_buf[size]; \
+ scalar_type dst_buf[size]; \
+ for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \
+ for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \
+ /* Copy all of src_buf onto the heap. */ \
+ env_->set_region_fn(a, 0, size, src_buf); \
+ /* Copy back only part. */ \
+ env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \
+ EXPECT_FALSE(memcmp(src_buf, dst_buf, sizeof(src_buf)) == 0) << "short copy equal"; \
+ /* Copy the missing pieces. */ \
+ env_->get_region_fn(a, 0, 1, dst_buf); \
+ env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \
+ EXPECT_TRUE(memcmp(src_buf, dst_buf, sizeof(src_buf)) == 0) << "fixed copy not equal"; \
+ /* Copy back the whole array. */ \
+ env_->get_region_fn(a, 0, size, dst_buf); \
+ EXPECT_TRUE(memcmp(src_buf, dst_buf, sizeof(src_buf)) == 0) << "full copy not equal"
-TEST_F(JniInternalTest, NewPrimitiveArray) {
- // TODO: death tests for negative array sizes.
-
- EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, 0, "[Z");
- EXPECT_PRIMITIVE_ARRAY(NewByteArray, 0, "[B");
- EXPECT_PRIMITIVE_ARRAY(NewCharArray, 0, "[C");
- EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, 0, "[D");
- EXPECT_PRIMITIVE_ARRAY(NewFloatArray, 0, "[F");
- EXPECT_PRIMITIVE_ARRAY(NewIntArray, 0, "[I");
- EXPECT_PRIMITIVE_ARRAY(NewLongArray, 0, "[J");
- EXPECT_PRIMITIVE_ARRAY(NewShortArray, 0, "[S");
-
- EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, 1, "[Z");
- EXPECT_PRIMITIVE_ARRAY(NewByteArray, 1, "[B");
- EXPECT_PRIMITIVE_ARRAY(NewCharArray, 1, "[C");
- EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, 1, "[D");
- EXPECT_PRIMITIVE_ARRAY(NewFloatArray, 1, "[F");
- EXPECT_PRIMITIVE_ARRAY(NewIntArray, 1, "[I");
- EXPECT_PRIMITIVE_ARRAY(NewLongArray, 1, "[J");
- EXPECT_PRIMITIVE_ARRAY(NewShortArray, 1, "[S");
+TEST_F(JniInternalTest, BooleanArrays) {
+ EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion, jboolean, "[Z");
+}
+TEST_F(JniInternalTest, ByteArrays) {
+ EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion, jbyte, "[B");
+}
+TEST_F(JniInternalTest, CharArrays) {
+ EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion, jchar, "[C");
+}
+TEST_F(JniInternalTest, DoubleArrays) {
+ EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion, jdouble, "[D");
+}
+TEST_F(JniInternalTest, FloatArrays) {
+ EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion, jfloat, "[F");
+}
+TEST_F(JniInternalTest, IntArrays) {
+ EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion, jint, "[I");
+}
+TEST_F(JniInternalTest, LongArrays) {
+ EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion, jlong, "[J");
+}
+TEST_F(JniInternalTest, ShortArrays) {
+ EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion, jshort, "[S");
}
TEST_F(JniInternalTest, NewObjectArray) {
@@ -353,28 +390,54 @@
TEST_F(JniInternalTest, NewStringUTF) {
EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
- EXPECT_TRUE(env_->NewStringUTF("") != NULL);
- EXPECT_TRUE(env_->NewStringUTF("hello") != NULL);
+ jstring s;
+
+ s = env_->NewStringUTF("");
+ EXPECT_TRUE(s != NULL);
+ EXPECT_EQ(0, env_->GetStringLength(s));
+ EXPECT_EQ(0, env_->GetStringUTFLength(s));
+ s = env_->NewStringUTF("hello");
+ EXPECT_TRUE(s != NULL);
+ EXPECT_EQ(5, env_->GetStringLength(s));
+ EXPECT_EQ(5, env_->GetStringUTFLength(s));
+
// TODO: check some non-ASCII strings.
}
-TEST_F(JniInternalTest, SetObjectArrayElement) {
- jclass aioobe = env_->FindClass("java/lang/ArrayIndexOutOfBoundsException");
+TEST_F(JniInternalTest, NewString) {
+ EXPECT_TRUE(env_->NewString(NULL, 0) == NULL);
+
+ jchar chars[] = { 'h', 'i' };
+ jstring s;
+ s = env_->NewString(chars, 0);
+ EXPECT_TRUE(s != NULL);
+ EXPECT_EQ(0, env_->GetStringLength(s));
+ EXPECT_EQ(0, env_->GetStringUTFLength(s));
+ s = env_->NewString(chars, 2);
+ EXPECT_TRUE(s != NULL);
+ EXPECT_EQ(2, env_->GetStringLength(s));
+ EXPECT_EQ(2, env_->GetStringUTFLength(s));
+
+ // TODO: check some non-ASCII strings.
+}
+
+TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
jclass c = env_->FindClass("[Ljava/lang/Object;");
ASSERT_TRUE(c != NULL);
jobjectArray array = env_->NewObjectArray(1, c, NULL);
EXPECT_TRUE(array != NULL);
+ EXPECT_TRUE(env_->GetObjectArrayElement(array, 0) == NULL);
env_->SetObjectArrayElement(array, 0, c);
- // TODO: check reading value back
+ EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), c));
// ArrayIndexOutOfBounds for negative index.
env_->SetObjectArrayElement(array, -1, c);
- EXPECT_EXCEPTION(aioobe);
+ EXPECT_EXCEPTION(aioobe_);
// ArrayIndexOutOfBounds for too-large index.
env_->SetObjectArrayElement(array, 1, c);
- EXPECT_EXCEPTION(aioobe);
+ EXPECT_EXCEPTION(aioobe_);
// TODO: check ArrayStoreException thrown for bad types.
}