627 lines
21 KiB
C++
627 lines
21 KiB
C++
// Copyright 2012 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/android/jni_array.h"
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include <algorithm>
|
|
#include <limits>
|
|
|
|
#include "base/android/jni_android.h"
|
|
#include "base/android/jni_string.h"
|
|
#include "base/android/scoped_java_ref.h"
|
|
#include "base/containers/span.h"
|
|
#include "base/strings/utf_string_conversions.h"
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace base::android {
|
|
|
|
TEST(JniArray, GetLength) {
|
|
const uint8_t bytes[] = {0, 1, 2, 3};
|
|
const size_t len = std::size(bytes);
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jbyteArray> j_bytes = ToJavaByteArray(env, bytes, len);
|
|
ASSERT_TRUE(j_bytes);
|
|
ASSERT_EQ(4U, SafeGetArrayLength(env, j_bytes));
|
|
|
|
ScopedJavaLocalRef<jbyteArray> j_empty_bytes =
|
|
ToJavaByteArray(env, base::span<uint8_t>());
|
|
ASSERT_TRUE(j_empty_bytes);
|
|
ASSERT_EQ(0U, SafeGetArrayLength(env, j_empty_bytes));
|
|
}
|
|
|
|
TEST(JniArray, BasicConversions) {
|
|
const uint8_t kBytes[] = {0, 1, 2, 3};
|
|
const size_t kLen = std::size(kBytes);
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jbyteArray> bytes = ToJavaByteArray(env, kBytes, kLen);
|
|
ASSERT_TRUE(bytes);
|
|
|
|
std::vector<uint8_t> inputVector(kBytes, kBytes + kLen);
|
|
ScopedJavaLocalRef<jbyteArray> bytesFromVector =
|
|
ToJavaByteArray(env, inputVector);
|
|
ASSERT_TRUE(bytesFromVector);
|
|
|
|
std::vector<uint8_t> vectorFromBytes(5);
|
|
std::vector<uint8_t> vectorFromVector(5);
|
|
JavaByteArrayToByteVector(env, bytes, &vectorFromBytes);
|
|
JavaByteArrayToByteVector(env, bytesFromVector, &vectorFromVector);
|
|
EXPECT_EQ(4U, vectorFromBytes.size());
|
|
EXPECT_EQ(4U, vectorFromVector.size());
|
|
std::vector<uint8_t> expected_vec(kBytes, kBytes + kLen);
|
|
EXPECT_EQ(expected_vec, vectorFromBytes);
|
|
EXPECT_EQ(expected_vec, vectorFromVector);
|
|
|
|
std::vector<uint8_t> vector_for_span_test(expected_vec.size());
|
|
JavaByteArrayToByteSpan(env, bytes, base::make_span(vector_for_span_test));
|
|
EXPECT_EQ(expected_vec, vector_for_span_test);
|
|
|
|
AppendJavaByteArrayToByteVector(env, bytes, &vectorFromBytes);
|
|
EXPECT_EQ(8U, vectorFromBytes.size());
|
|
expected_vec.insert(expected_vec.end(), kBytes, kBytes + kLen);
|
|
EXPECT_EQ(expected_vec, vectorFromBytes);
|
|
}
|
|
|
|
TEST(JniArray, ByteArrayStringConversions) {
|
|
JNIEnv* env = AttachCurrentThread();
|
|
std::string inputString("hello\0world");
|
|
ScopedJavaLocalRef<jbyteArray> bytesFromString =
|
|
ToJavaByteArray(env, inputString);
|
|
ASSERT_TRUE(bytesFromString);
|
|
|
|
std::string stringFromString;
|
|
JavaByteArrayToString(env, bytesFromString, &stringFromString);
|
|
EXPECT_EQ(inputString, stringFromString);
|
|
}
|
|
|
|
void CheckBoolConversion(JNIEnv* env,
|
|
const bool* bool_array,
|
|
const size_t len,
|
|
const ScopedJavaLocalRef<jbooleanArray>& booleans) {
|
|
ASSERT_TRUE(booleans);
|
|
|
|
jsize java_array_len = env->GetArrayLength(booleans.obj());
|
|
ASSERT_EQ(static_cast<jsize>(len), java_array_len);
|
|
|
|
jboolean value;
|
|
for (size_t i = 0; i < len; ++i) {
|
|
env->GetBooleanArrayRegion(booleans.obj(), i, 1, &value);
|
|
ASSERT_EQ(bool_array[i], value);
|
|
}
|
|
}
|
|
|
|
TEST(JniArray, BoolConversions) {
|
|
const bool kBools[] = {false, true, false};
|
|
const size_t kLen = std::size(kBools);
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
CheckBoolConversion(env, kBools, kLen, ToJavaBooleanArray(env, kBools, kLen));
|
|
}
|
|
|
|
void CheckIntConversion(
|
|
JNIEnv* env,
|
|
const int* int_array,
|
|
const size_t len,
|
|
const ScopedJavaLocalRef<jintArray>& ints) {
|
|
ASSERT_TRUE(ints);
|
|
|
|
jsize java_array_len = env->GetArrayLength(ints.obj());
|
|
ASSERT_EQ(static_cast<jsize>(len), java_array_len);
|
|
|
|
jint value;
|
|
for (size_t i = 0; i < len; ++i) {
|
|
env->GetIntArrayRegion(ints.obj(), i, 1, &value);
|
|
ASSERT_EQ(int_array[i], value);
|
|
}
|
|
}
|
|
|
|
TEST(JniArray, IntConversions) {
|
|
const int kInts[] = {0, 1, -1, std::numeric_limits<int32_t>::min(),
|
|
std::numeric_limits<int32_t>::max()};
|
|
const size_t kLen = std::size(kInts);
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
CheckIntConversion(env, kInts, kLen, ToJavaIntArray(env, kInts, kLen));
|
|
|
|
const std::vector<int> vec(kInts, kInts + kLen);
|
|
CheckIntConversion(env, kInts, kLen, ToJavaIntArray(env, vec));
|
|
}
|
|
|
|
void CheckLongConversion(JNIEnv* env,
|
|
const int64_t* long_array,
|
|
const size_t len,
|
|
const ScopedJavaLocalRef<jlongArray>& longs) {
|
|
ASSERT_TRUE(longs);
|
|
|
|
jsize java_array_len = env->GetArrayLength(longs.obj());
|
|
ASSERT_EQ(static_cast<jsize>(len), java_array_len);
|
|
|
|
jlong value;
|
|
for (size_t i = 0; i < len; ++i) {
|
|
env->GetLongArrayRegion(longs.obj(), i, 1, &value);
|
|
ASSERT_EQ(long_array[i], value);
|
|
}
|
|
}
|
|
|
|
TEST(JniArray, LongConversions) {
|
|
const int64_t kLongs[] = {0, 1, -1, std::numeric_limits<int64_t>::min(),
|
|
std::numeric_limits<int64_t>::max()};
|
|
const size_t kLen = std::size(kLongs);
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
CheckLongConversion(env, kLongs, kLen, ToJavaLongArray(env, kLongs, kLen));
|
|
|
|
const std::vector<int64_t> vec(kLongs, kLongs + kLen);
|
|
CheckLongConversion(env, kLongs, kLen, ToJavaLongArray(env, vec));
|
|
}
|
|
|
|
void CheckIntArrayConversion(JNIEnv* env,
|
|
ScopedJavaLocalRef<jintArray> jints,
|
|
std::vector<int> int_vector,
|
|
const size_t len) {
|
|
jint value;
|
|
for (size_t i = 0; i < len; ++i) {
|
|
env->GetIntArrayRegion(jints.obj(), i, 1, &value);
|
|
ASSERT_EQ(int_vector[i], value);
|
|
}
|
|
}
|
|
|
|
void CheckBoolArrayConversion(JNIEnv* env,
|
|
ScopedJavaLocalRef<jbooleanArray> jbooleans,
|
|
std::vector<bool> bool_vector,
|
|
const size_t len) {
|
|
jboolean value;
|
|
for (size_t i = 0; i < len; ++i) {
|
|
env->GetBooleanArrayRegion(jbooleans.obj(), i, 1, &value);
|
|
ASSERT_EQ(bool_vector[i], value);
|
|
}
|
|
}
|
|
|
|
void CheckFloatConversion(
|
|
JNIEnv* env,
|
|
const float* float_array,
|
|
const size_t len,
|
|
const ScopedJavaLocalRef<jfloatArray>& floats) {
|
|
ASSERT_TRUE(floats);
|
|
|
|
jsize java_array_len = env->GetArrayLength(floats.obj());
|
|
ASSERT_EQ(static_cast<jsize>(len), java_array_len);
|
|
|
|
jfloat value;
|
|
for (size_t i = 0; i < len; ++i) {
|
|
env->GetFloatArrayRegion(floats.obj(), i, 1, &value);
|
|
ASSERT_EQ(float_array[i], value);
|
|
}
|
|
}
|
|
|
|
TEST(JniArray, ArrayOfStringArrayConversionUTF8) {
|
|
std::vector<std::vector<std::string>> kArrays = {
|
|
{"a", "f"}, {"a", ""}, {}, {""}, {"今日は"}};
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jobjectArray> joa = ToJavaArrayOfStringArray(env, kArrays);
|
|
|
|
std::vector<std::vector<std::string>> out;
|
|
Java2dStringArrayTo2dStringVector(env, joa, &out);
|
|
ASSERT_TRUE(kArrays == out);
|
|
}
|
|
|
|
TEST(JniArray, ArrayOfStringArrayConversionUTF16) {
|
|
std::vector<std::vector<std::u16string>> kArrays = {
|
|
{u"a", u"f"}, {u"a", u""}, {}, {u""}};
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jobjectArray> joa = ToJavaArrayOfStringArray(env, kArrays);
|
|
|
|
std::vector<std::vector<std::u16string>> out;
|
|
Java2dStringArrayTo2dStringVector(env, joa, &out);
|
|
ASSERT_TRUE(kArrays == out);
|
|
}
|
|
|
|
TEST(JniArray, FloatConversions) {
|
|
const float kFloats[] = { 0.0f, 1.0f, -10.0f};
|
|
const size_t kLen = std::size(kFloats);
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
CheckFloatConversion(env, kFloats, kLen,
|
|
ToJavaFloatArray(env, kFloats, kLen));
|
|
|
|
const std::vector<float> vec(kFloats, kFloats + kLen);
|
|
CheckFloatConversion(env, kFloats, kLen, ToJavaFloatArray(env, vec));
|
|
}
|
|
|
|
TEST(JniArray, JavaBooleanArrayToBoolVector) {
|
|
const bool kBools[] = {false, true, false};
|
|
const size_t kLen = std::size(kBools);
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jbooleanArray> jbooleans(env, env->NewBooleanArray(kLen));
|
|
ASSERT_TRUE(jbooleans);
|
|
|
|
for (size_t i = 0; i < kLen; ++i) {
|
|
jboolean j = static_cast<jboolean>(kBools[i]);
|
|
env->SetBooleanArrayRegion(jbooleans.obj(), i, 1, &j);
|
|
ASSERT_FALSE(HasException(env));
|
|
}
|
|
|
|
std::vector<bool> bools;
|
|
JavaBooleanArrayToBoolVector(env, jbooleans, &bools);
|
|
|
|
ASSERT_EQ(static_cast<jsize>(bools.size()),
|
|
env->GetArrayLength(jbooleans.obj()));
|
|
|
|
CheckBoolArrayConversion(env, jbooleans, bools, kLen);
|
|
}
|
|
|
|
TEST(JniArray, JavaIntArrayToIntVector) {
|
|
const int kInts[] = {0, 1, -1};
|
|
const size_t kLen = std::size(kInts);
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jintArray> jints(env, env->NewIntArray(kLen));
|
|
ASSERT_TRUE(jints);
|
|
|
|
for (size_t i = 0; i < kLen; ++i) {
|
|
jint j = static_cast<jint>(kInts[i]);
|
|
env->SetIntArrayRegion(jints.obj(), i, 1, &j);
|
|
ASSERT_FALSE(HasException(env));
|
|
}
|
|
|
|
std::vector<int> ints;
|
|
JavaIntArrayToIntVector(env, jints, &ints);
|
|
|
|
ASSERT_EQ(static_cast<jsize>(ints.size()), env->GetArrayLength(jints.obj()));
|
|
|
|
CheckIntArrayConversion(env, jints, ints, kLen);
|
|
}
|
|
|
|
TEST(JniArray, JavaLongArrayToInt64Vector) {
|
|
const int64_t kInt64s[] = {0LL, 1LL, -1LL};
|
|
const size_t kLen = std::size(kInt64s);
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jlongArray> jlongs(env, env->NewLongArray(kLen));
|
|
ASSERT_TRUE(jlongs);
|
|
|
|
for (size_t i = 0; i < kLen; ++i) {
|
|
jlong j = static_cast<jlong>(kInt64s[i]);
|
|
env->SetLongArrayRegion(jlongs.obj(), i, 1, &j);
|
|
ASSERT_FALSE(HasException(env));
|
|
}
|
|
|
|
std::vector<int64_t> int64s;
|
|
JavaLongArrayToInt64Vector(env, jlongs, &int64s);
|
|
|
|
ASSERT_EQ(static_cast<jsize>(int64s.size()),
|
|
env->GetArrayLength(jlongs.obj()));
|
|
|
|
jlong value;
|
|
for (size_t i = 0; i < kLen; ++i) {
|
|
env->GetLongArrayRegion(jlongs.obj(), i, 1, &value);
|
|
ASSERT_EQ(int64s[i], value);
|
|
ASSERT_EQ(kInt64s[i], int64s[i]);
|
|
}
|
|
}
|
|
|
|
TEST(JniArray, JavaLongArrayToLongVector) {
|
|
const int64_t kInt64s[] = {0LL, 1LL, -1LL};
|
|
const size_t kLen = std::size(kInt64s);
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jlongArray> jlongs(env, env->NewLongArray(kLen));
|
|
ASSERT_TRUE(jlongs);
|
|
|
|
for (size_t i = 0; i < kLen; ++i) {
|
|
jlong j = static_cast<jlong>(kInt64s[i]);
|
|
env->SetLongArrayRegion(jlongs.obj(), i, 1, &j);
|
|
ASSERT_FALSE(HasException(env));
|
|
}
|
|
|
|
std::vector<jlong> jlongs_vector;
|
|
JavaLongArrayToLongVector(env, jlongs, &jlongs_vector);
|
|
|
|
ASSERT_EQ(static_cast<jsize>(jlongs_vector.size()),
|
|
env->GetArrayLength(jlongs.obj()));
|
|
|
|
jlong value;
|
|
for (size_t i = 0; i < kLen; ++i) {
|
|
env->GetLongArrayRegion(jlongs.obj(), i, 1, &value);
|
|
ASSERT_EQ(jlongs_vector[i], value);
|
|
}
|
|
}
|
|
|
|
TEST(JniArray, JavaFloatArrayToFloatVector) {
|
|
const float kFloats[] = {0.0, 0.5, -0.5};
|
|
const size_t kLen = std::size(kFloats);
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jfloatArray> jfloats(env, env->NewFloatArray(kLen));
|
|
ASSERT_TRUE(jfloats);
|
|
|
|
for (size_t i = 0; i < kLen; ++i) {
|
|
jfloat j = static_cast<jfloat>(kFloats[i]);
|
|
env->SetFloatArrayRegion(jfloats.obj(), i, 1, &j);
|
|
ASSERT_FALSE(HasException(env));
|
|
}
|
|
|
|
std::vector<float> floats;
|
|
JavaFloatArrayToFloatVector(env, jfloats, &floats);
|
|
|
|
ASSERT_EQ(static_cast<jsize>(floats.size()),
|
|
env->GetArrayLength(jfloats.obj()));
|
|
|
|
jfloat value;
|
|
for (size_t i = 0; i < kLen; ++i) {
|
|
env->GetFloatArrayRegion(jfloats.obj(), i, 1, &value);
|
|
ASSERT_EQ(floats[i], value);
|
|
}
|
|
}
|
|
|
|
TEST(JniArray, JavaDoubleArrayToDoubleVector) {
|
|
const std::vector<double> kDoubles = {0.0, 0.5, -0.5,
|
|
std::numeric_limits<double>::min()};
|
|
JNIEnv* env = AttachCurrentThread();
|
|
ScopedJavaLocalRef<jdoubleArray> jdoubles(
|
|
env, env->NewDoubleArray(kDoubles.size()));
|
|
ASSERT_TRUE(jdoubles);
|
|
|
|
env->SetDoubleArrayRegion(jdoubles.obj(), 0, kDoubles.size(),
|
|
reinterpret_cast<const jdouble*>(kDoubles.data()));
|
|
ASSERT_FALSE(HasException(env));
|
|
|
|
std::vector<double> doubles;
|
|
JavaDoubleArrayToDoubleVector(env, jdoubles, &doubles);
|
|
ASSERT_EQ(kDoubles, doubles);
|
|
}
|
|
|
|
TEST(JniArray, JavaArrayOfByteArrayToStringVector) {
|
|
const int kMaxItems = 50;
|
|
JNIEnv* env = AttachCurrentThread();
|
|
|
|
// Create a byte[][] object.
|
|
ScopedJavaLocalRef<jclass> byte_array_clazz(env, env->FindClass("[B"));
|
|
ASSERT_TRUE(byte_array_clazz);
|
|
|
|
ScopedJavaLocalRef<jobjectArray> array(
|
|
env, env->NewObjectArray(kMaxItems, byte_array_clazz.obj(), NULL));
|
|
ASSERT_TRUE(array);
|
|
|
|
// Create kMaxItems byte buffers.
|
|
char text[16];
|
|
for (int i = 0; i < kMaxItems; ++i) {
|
|
snprintf(text, sizeof text, "%d", i);
|
|
ScopedJavaLocalRef<jbyteArray> byte_array =
|
|
ToJavaByteArray(env, reinterpret_cast<uint8_t*>(text),
|
|
static_cast<size_t>(strlen(text)));
|
|
ASSERT_TRUE(byte_array);
|
|
|
|
env->SetObjectArrayElement(array.obj(), i, byte_array.obj());
|
|
ASSERT_FALSE(HasException(env));
|
|
}
|
|
|
|
// Convert to std::vector<std::string>, check the content.
|
|
std::vector<std::string> vec;
|
|
JavaArrayOfByteArrayToStringVector(env, array, &vec);
|
|
|
|
EXPECT_EQ(static_cast<size_t>(kMaxItems), vec.size());
|
|
for (int i = 0; i < kMaxItems; ++i) {
|
|
snprintf(text, sizeof text, "%d", i);
|
|
EXPECT_STREQ(text, vec[i].c_str());
|
|
}
|
|
}
|
|
|
|
TEST(JniArray, JavaArrayOfByteArrayToBytesVector) {
|
|
const size_t kMaxItems = 50;
|
|
const uint8_t kStep = 37;
|
|
JNIEnv* env = AttachCurrentThread();
|
|
|
|
// Create a byte[][] object.
|
|
ScopedJavaLocalRef<jclass> byte_array_clazz(env, env->FindClass("[B"));
|
|
ASSERT_TRUE(byte_array_clazz);
|
|
|
|
ScopedJavaLocalRef<jobjectArray> array(
|
|
env, env->NewObjectArray(kMaxItems, byte_array_clazz.obj(), nullptr));
|
|
ASSERT_TRUE(array);
|
|
|
|
// Create kMaxItems byte buffers with size |i|+1 on each step;
|
|
std::vector<std::vector<uint8_t>> input_bytes;
|
|
input_bytes.reserve(kMaxItems);
|
|
for (size_t i = 0; i < kMaxItems; ++i) {
|
|
std::vector<uint8_t> cur_bytes(i + 1);
|
|
for (size_t j = 0; j < cur_bytes.size(); ++j)
|
|
cur_bytes[j] = static_cast<uint8_t>(i + j * kStep);
|
|
ScopedJavaLocalRef<jbyteArray> byte_array =
|
|
ToJavaByteArray(env, cur_bytes.data(), cur_bytes.size());
|
|
ASSERT_TRUE(byte_array);
|
|
|
|
env->SetObjectArrayElement(array.obj(), i, byte_array.obj());
|
|
ASSERT_FALSE(HasException(env));
|
|
|
|
input_bytes.push_back(std::move(cur_bytes));
|
|
}
|
|
ASSERT_EQ(kMaxItems, input_bytes.size());
|
|
|
|
// Convert to std::vector<std::vector<uint8_t>>, check the content.
|
|
std::vector<std::vector<uint8_t>> result;
|
|
JavaArrayOfByteArrayToBytesVector(env, array, &result);
|
|
|
|
EXPECT_EQ(input_bytes.size(), result.size());
|
|
for (size_t i = 0; i < kMaxItems; ++i)
|
|
EXPECT_THAT(result[i], ::testing::ElementsAreArray(input_bytes.at(i)));
|
|
}
|
|
|
|
TEST(JniArray, JavaArrayOfStringArrayToVectorOfStringVector) {
|
|
const std::vector<std::vector<std::u16string>> kArrays = {
|
|
{u"a", u"f"}, {u"a", u""}, {}, {u""}};
|
|
|
|
JNIEnv* env = AttachCurrentThread();
|
|
|
|
ScopedJavaLocalRef<jobjectArray> array(
|
|
env, env->NewObjectArray(kArrays.size(),
|
|
env->FindClass("[Ljava/lang/String;"), NULL));
|
|
ASSERT_TRUE(array);
|
|
|
|
ScopedJavaLocalRef<jclass> string_clazz(env,
|
|
env->FindClass("java/lang/String"));
|
|
ASSERT_TRUE(string_clazz);
|
|
|
|
for (size_t i = 0; i < kArrays.size(); ++i) {
|
|
const std::vector<std::u16string>& child_data = kArrays[i];
|
|
|
|
ScopedJavaLocalRef<jobjectArray> child_array(
|
|
env, env->NewObjectArray(child_data.size(), string_clazz.obj(), NULL));
|
|
ASSERT_TRUE(child_array);
|
|
|
|
for (size_t j = 0; j < child_data.size(); ++j) {
|
|
ScopedJavaLocalRef<jstring> item =
|
|
base::android::ConvertUTF16ToJavaString(env, child_data[j]);
|
|
env->SetObjectArrayElement(child_array.obj(), j, item.obj());
|
|
ASSERT_FALSE(HasException(env));
|
|
}
|
|
env->SetObjectArrayElement(array.obj(), i, child_array.obj());
|
|
}
|
|
|
|
std::vector<std::vector<std::u16string>> vec;
|
|
Java2dStringArrayTo2dStringVector(env, array, &vec);
|
|
|
|
ASSERT_EQ(kArrays, vec);
|
|
}
|
|
|
|
TEST(JniArray, JavaArrayOfIntArrayToIntVector) {
|
|
const size_t kNumItems = 4;
|
|
JNIEnv* env = AttachCurrentThread();
|
|
|
|
// Create an int[][] object.
|
|
ScopedJavaLocalRef<jclass> int_array_clazz(env, env->FindClass("[I"));
|
|
ASSERT_TRUE(int_array_clazz);
|
|
|
|
ScopedJavaLocalRef<jobjectArray> array(
|
|
env, env->NewObjectArray(kNumItems, int_array_clazz.obj(), nullptr));
|
|
ASSERT_TRUE(array);
|
|
|
|
// Populate int[][] object.
|
|
const int kInts0[] = {0, 1, -1, std::numeric_limits<int32_t>::min(),
|
|
std::numeric_limits<int32_t>::max()};
|
|
const size_t kLen0 = std::size(kInts0);
|
|
ScopedJavaLocalRef<jintArray> int_array0 = ToJavaIntArray(env, kInts0, kLen0);
|
|
env->SetObjectArrayElement(array.obj(), 0, int_array0.obj());
|
|
|
|
const int kInts1[] = {3, 4, 5};
|
|
const size_t kLen1 = std::size(kInts1);
|
|
ScopedJavaLocalRef<jintArray> int_array1 = ToJavaIntArray(env, kInts1, kLen1);
|
|
env->SetObjectArrayElement(array.obj(), 1, int_array1.obj());
|
|
|
|
const int kInts2[] = {};
|
|
const size_t kLen2 = 0;
|
|
ScopedJavaLocalRef<jintArray> int_array2 = ToJavaIntArray(env, kInts2, kLen2);
|
|
env->SetObjectArrayElement(array.obj(), 2, int_array2.obj());
|
|
|
|
const int kInts3[] = {16};
|
|
const size_t kLen3 = std::size(kInts3);
|
|
ScopedJavaLocalRef<jintArray> int_array3 = ToJavaIntArray(env, kInts3, kLen3);
|
|
env->SetObjectArrayElement(array.obj(), 3, int_array3.obj());
|
|
|
|
// Convert to std::vector<std::vector<int>>, check the content.
|
|
std::vector<std::vector<int>> out;
|
|
JavaArrayOfIntArrayToIntVector(env, array, &out);
|
|
|
|
EXPECT_EQ(kNumItems, out.size());
|
|
CheckIntArrayConversion(env, int_array0, out[0], kLen0);
|
|
CheckIntArrayConversion(env, int_array1, out[1], kLen1);
|
|
CheckIntArrayConversion(env, int_array2, out[2], kLen2);
|
|
CheckIntArrayConversion(env, int_array3, out[3], kLen3);
|
|
}
|
|
|
|
TEST(JniArray, ToJavaArrayOfObjectsOfClass) {
|
|
JNIEnv* env = AttachCurrentThread();
|
|
|
|
std::vector<ScopedJavaLocalRef<jobject>> objects = {
|
|
ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "one")),
|
|
ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "two")),
|
|
ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "three")),
|
|
};
|
|
|
|
ScopedJavaLocalRef<jobjectArray> j_array =
|
|
ToJavaArrayOfObjects(env, GetClass(env, "java/lang/String"), objects);
|
|
ASSERT_TRUE(j_array);
|
|
|
|
EXPECT_EQ("one",
|
|
ConvertJavaStringToUTF8(
|
|
env, ScopedJavaLocalRef<jstring>(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(
|
|
j_array.obj(), 0)))));
|
|
EXPECT_EQ("two",
|
|
ConvertJavaStringToUTF8(
|
|
env, ScopedJavaLocalRef<jstring>(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(
|
|
j_array.obj(), 1)))));
|
|
EXPECT_EQ("three",
|
|
ConvertJavaStringToUTF8(
|
|
env, ScopedJavaLocalRef<jstring>(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(
|
|
j_array.obj(), 2)))));
|
|
}
|
|
|
|
TEST(JniArray, ToJavaArrayOfObjectLocalRef) {
|
|
JNIEnv* env = AttachCurrentThread();
|
|
|
|
std::vector<ScopedJavaLocalRef<jobject>> objects = {
|
|
ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "one")),
|
|
ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "two")),
|
|
ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "three")),
|
|
};
|
|
|
|
ScopedJavaLocalRef<jobjectArray> j_array = ToJavaArrayOfObjects(env, objects);
|
|
ASSERT_TRUE(j_array);
|
|
|
|
EXPECT_EQ("one",
|
|
ConvertJavaStringToUTF8(
|
|
env, ScopedJavaLocalRef<jstring>(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(
|
|
j_array.obj(), 0)))));
|
|
EXPECT_EQ("two",
|
|
ConvertJavaStringToUTF8(
|
|
env, ScopedJavaLocalRef<jstring>(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(
|
|
j_array.obj(), 1)))));
|
|
EXPECT_EQ("three",
|
|
ConvertJavaStringToUTF8(
|
|
env, ScopedJavaLocalRef<jstring>(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(
|
|
j_array.obj(), 2)))));
|
|
}
|
|
|
|
TEST(JniArray, ToJavaArrayOfObjectGlobalRef) {
|
|
JNIEnv* env = AttachCurrentThread();
|
|
|
|
std::vector<ScopedJavaGlobalRef<jobject>> objects = {
|
|
ScopedJavaGlobalRef<jobject>(ConvertUTF8ToJavaString(env, "one")),
|
|
ScopedJavaGlobalRef<jobject>(ConvertUTF8ToJavaString(env, "two")),
|
|
ScopedJavaGlobalRef<jobject>(ConvertUTF8ToJavaString(env, "three")),
|
|
};
|
|
|
|
ScopedJavaLocalRef<jobjectArray> j_array = ToJavaArrayOfObjects(env, objects);
|
|
ASSERT_TRUE(j_array);
|
|
|
|
EXPECT_EQ("one",
|
|
ConvertJavaStringToUTF8(
|
|
env, ScopedJavaLocalRef<jstring>(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(
|
|
j_array.obj(), 0)))));
|
|
EXPECT_EQ("two",
|
|
ConvertJavaStringToUTF8(
|
|
env, ScopedJavaLocalRef<jstring>(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(
|
|
j_array.obj(), 1)))));
|
|
EXPECT_EQ("three",
|
|
ConvertJavaStringToUTF8(
|
|
env, ScopedJavaLocalRef<jstring>(
|
|
env, static_cast<jstring>(env->GetObjectArrayElement(
|
|
j_array.obj(), 2)))));
|
|
}
|
|
} // namespace base::android
|