1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/android/jni_array.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <algorithm>
11 #include <limits>
12
13 #include "base/android/jni_android.h"
14 #include "base/android/jni_string.h"
15 #include "base/android/scoped_java_ref.h"
16 #include "base/containers/span.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace base::android {
22
TEST(JniArray,GetLength)23 TEST(JniArray, GetLength) {
24 const uint8_t bytes[] = {0, 1, 2, 3};
25 const size_t len = std::size(bytes);
26 JNIEnv* env = AttachCurrentThread();
27 ScopedJavaLocalRef<jbyteArray> j_bytes = ToJavaByteArray(env, bytes, len);
28 ASSERT_TRUE(j_bytes);
29 ASSERT_EQ(4U, SafeGetArrayLength(env, j_bytes));
30
31 ScopedJavaLocalRef<jbyteArray> j_empty_bytes =
32 ToJavaByteArray(env, base::span<uint8_t>());
33 ASSERT_TRUE(j_empty_bytes);
34 ASSERT_EQ(0U, SafeGetArrayLength(env, j_empty_bytes));
35 }
36
TEST(JniArray,BasicConversions)37 TEST(JniArray, BasicConversions) {
38 const uint8_t kBytes[] = {0, 1, 2, 3};
39 const size_t kLen = std::size(kBytes);
40 JNIEnv* env = AttachCurrentThread();
41 ScopedJavaLocalRef<jbyteArray> bytes = ToJavaByteArray(env, kBytes, kLen);
42 ASSERT_TRUE(bytes);
43
44 std::vector<uint8_t> inputVector(kBytes, kBytes + kLen);
45 ScopedJavaLocalRef<jbyteArray> bytesFromVector =
46 ToJavaByteArray(env, inputVector);
47 ASSERT_TRUE(bytesFromVector);
48
49 std::vector<uint8_t> vectorFromBytes(5);
50 std::vector<uint8_t> vectorFromVector(5);
51 JavaByteArrayToByteVector(env, bytes, &vectorFromBytes);
52 JavaByteArrayToByteVector(env, bytesFromVector, &vectorFromVector);
53 EXPECT_EQ(4U, vectorFromBytes.size());
54 EXPECT_EQ(4U, vectorFromVector.size());
55 std::vector<uint8_t> expected_vec(kBytes, kBytes + kLen);
56 EXPECT_EQ(expected_vec, vectorFromBytes);
57 EXPECT_EQ(expected_vec, vectorFromVector);
58
59 std::vector<uint8_t> vector_for_span_test(expected_vec.size());
60 JavaByteArrayToByteSpan(env, bytes, base::make_span(vector_for_span_test));
61 EXPECT_EQ(expected_vec, vector_for_span_test);
62
63 AppendJavaByteArrayToByteVector(env, bytes, &vectorFromBytes);
64 EXPECT_EQ(8U, vectorFromBytes.size());
65 expected_vec.insert(expected_vec.end(), kBytes, kBytes + kLen);
66 EXPECT_EQ(expected_vec, vectorFromBytes);
67 }
68
TEST(JniArray,ByteArrayStringConversions)69 TEST(JniArray, ByteArrayStringConversions) {
70 JNIEnv* env = AttachCurrentThread();
71 std::string inputString("hello\0world");
72 ScopedJavaLocalRef<jbyteArray> bytesFromString =
73 ToJavaByteArray(env, inputString);
74 ASSERT_TRUE(bytesFromString);
75
76 std::string stringFromString;
77 JavaByteArrayToString(env, bytesFromString, &stringFromString);
78 EXPECT_EQ(inputString, stringFromString);
79 }
80
CheckBoolConversion(JNIEnv * env,const bool * bool_array,const size_t len,const ScopedJavaLocalRef<jbooleanArray> & booleans)81 void CheckBoolConversion(JNIEnv* env,
82 const bool* bool_array,
83 const size_t len,
84 const ScopedJavaLocalRef<jbooleanArray>& booleans) {
85 ASSERT_TRUE(booleans);
86
87 jsize java_array_len = env->GetArrayLength(booleans.obj());
88 ASSERT_EQ(static_cast<jsize>(len), java_array_len);
89
90 jboolean value;
91 for (size_t i = 0; i < len; ++i) {
92 env->GetBooleanArrayRegion(booleans.obj(), i, 1, &value);
93 ASSERT_EQ(bool_array[i], value);
94 }
95 }
96
TEST(JniArray,BoolConversions)97 TEST(JniArray, BoolConversions) {
98 const bool kBools[] = {false, true, false};
99 const size_t kLen = std::size(kBools);
100
101 JNIEnv* env = AttachCurrentThread();
102 CheckBoolConversion(env, kBools, kLen, ToJavaBooleanArray(env, kBools, kLen));
103 }
104
CheckIntConversion(JNIEnv * env,const int * int_array,const size_t len,const ScopedJavaLocalRef<jintArray> & ints)105 void CheckIntConversion(
106 JNIEnv* env,
107 const int* int_array,
108 const size_t len,
109 const ScopedJavaLocalRef<jintArray>& ints) {
110 ASSERT_TRUE(ints);
111
112 jsize java_array_len = env->GetArrayLength(ints.obj());
113 ASSERT_EQ(static_cast<jsize>(len), java_array_len);
114
115 jint value;
116 for (size_t i = 0; i < len; ++i) {
117 env->GetIntArrayRegion(ints.obj(), i, 1, &value);
118 ASSERT_EQ(int_array[i], value);
119 }
120 }
121
TEST(JniArray,IntConversions)122 TEST(JniArray, IntConversions) {
123 const int kInts[] = {0, 1, -1, std::numeric_limits<int32_t>::min(),
124 std::numeric_limits<int32_t>::max()};
125 const size_t kLen = std::size(kInts);
126
127 JNIEnv* env = AttachCurrentThread();
128 CheckIntConversion(env, kInts, kLen, ToJavaIntArray(env, kInts, kLen));
129
130 const std::vector<int> vec(kInts, kInts + kLen);
131 CheckIntConversion(env, kInts, kLen, ToJavaIntArray(env, vec));
132 }
133
CheckLongConversion(JNIEnv * env,const int64_t * long_array,const size_t len,const ScopedJavaLocalRef<jlongArray> & longs)134 void CheckLongConversion(JNIEnv* env,
135 const int64_t* long_array,
136 const size_t len,
137 const ScopedJavaLocalRef<jlongArray>& longs) {
138 ASSERT_TRUE(longs);
139
140 jsize java_array_len = env->GetArrayLength(longs.obj());
141 ASSERT_EQ(static_cast<jsize>(len), java_array_len);
142
143 jlong value;
144 for (size_t i = 0; i < len; ++i) {
145 env->GetLongArrayRegion(longs.obj(), i, 1, &value);
146 ASSERT_EQ(long_array[i], value);
147 }
148 }
149
TEST(JniArray,LongConversions)150 TEST(JniArray, LongConversions) {
151 const int64_t kLongs[] = {0, 1, -1, std::numeric_limits<int64_t>::min(),
152 std::numeric_limits<int64_t>::max()};
153 const size_t kLen = std::size(kLongs);
154
155 JNIEnv* env = AttachCurrentThread();
156 CheckLongConversion(env, kLongs, kLen, ToJavaLongArray(env, kLongs, kLen));
157
158 const std::vector<int64_t> vec(kLongs, kLongs + kLen);
159 CheckLongConversion(env, kLongs, kLen, ToJavaLongArray(env, vec));
160 }
161
CheckIntArrayConversion(JNIEnv * env,ScopedJavaLocalRef<jintArray> jints,std::vector<int> int_vector,const size_t len)162 void CheckIntArrayConversion(JNIEnv* env,
163 ScopedJavaLocalRef<jintArray> jints,
164 std::vector<int> int_vector,
165 const size_t len) {
166 jint value;
167 for (size_t i = 0; i < len; ++i) {
168 env->GetIntArrayRegion(jints.obj(), i, 1, &value);
169 ASSERT_EQ(int_vector[i], value);
170 }
171 }
172
CheckBoolArrayConversion(JNIEnv * env,ScopedJavaLocalRef<jbooleanArray> jbooleans,std::vector<bool> bool_vector,const size_t len)173 void CheckBoolArrayConversion(JNIEnv* env,
174 ScopedJavaLocalRef<jbooleanArray> jbooleans,
175 std::vector<bool> bool_vector,
176 const size_t len) {
177 jboolean value;
178 for (size_t i = 0; i < len; ++i) {
179 env->GetBooleanArrayRegion(jbooleans.obj(), i, 1, &value);
180 ASSERT_EQ(bool_vector[i], value);
181 }
182 }
183
CheckFloatConversion(JNIEnv * env,const float * float_array,const size_t len,const ScopedJavaLocalRef<jfloatArray> & floats)184 void CheckFloatConversion(
185 JNIEnv* env,
186 const float* float_array,
187 const size_t len,
188 const ScopedJavaLocalRef<jfloatArray>& floats) {
189 ASSERT_TRUE(floats);
190
191 jsize java_array_len = env->GetArrayLength(floats.obj());
192 ASSERT_EQ(static_cast<jsize>(len), java_array_len);
193
194 jfloat value;
195 for (size_t i = 0; i < len; ++i) {
196 env->GetFloatArrayRegion(floats.obj(), i, 1, &value);
197 ASSERT_EQ(float_array[i], value);
198 }
199 }
200
TEST(JniArray,ArrayOfStringArrayConversionUTF8)201 TEST(JniArray, ArrayOfStringArrayConversionUTF8) {
202 std::vector<std::vector<std::string>> kArrays = {
203 {"a", "f"}, {"a", ""}, {}, {""}, {"今日は"}};
204
205 JNIEnv* env = AttachCurrentThread();
206 ScopedJavaLocalRef<jobjectArray> joa = ToJavaArrayOfStringArray(env, kArrays);
207
208 std::vector<std::vector<std::string>> out;
209 Java2dStringArrayTo2dStringVector(env, joa, &out);
210 ASSERT_TRUE(kArrays == out);
211 }
212
TEST(JniArray,ArrayOfStringArrayConversionUTF16)213 TEST(JniArray, ArrayOfStringArrayConversionUTF16) {
214 std::vector<std::vector<std::u16string>> kArrays = {
215 {u"a", u"f"}, {u"a", u""}, {}, {u""}};
216
217 JNIEnv* env = AttachCurrentThread();
218 ScopedJavaLocalRef<jobjectArray> joa = ToJavaArrayOfStringArray(env, kArrays);
219
220 std::vector<std::vector<std::u16string>> out;
221 Java2dStringArrayTo2dStringVector(env, joa, &out);
222 ASSERT_TRUE(kArrays == out);
223 }
224
TEST(JniArray,FloatConversions)225 TEST(JniArray, FloatConversions) {
226 const float kFloats[] = { 0.0f, 1.0f, -10.0f};
227 const size_t kLen = std::size(kFloats);
228
229 JNIEnv* env = AttachCurrentThread();
230 CheckFloatConversion(env, kFloats, kLen,
231 ToJavaFloatArray(env, kFloats, kLen));
232
233 const std::vector<float> vec(kFloats, kFloats + kLen);
234 CheckFloatConversion(env, kFloats, kLen, ToJavaFloatArray(env, vec));
235 }
236
TEST(JniArray,JavaBooleanArrayToBoolVector)237 TEST(JniArray, JavaBooleanArrayToBoolVector) {
238 const bool kBools[] = {false, true, false};
239 const size_t kLen = std::size(kBools);
240
241 JNIEnv* env = AttachCurrentThread();
242 ScopedJavaLocalRef<jbooleanArray> jbooleans(env, env->NewBooleanArray(kLen));
243 ASSERT_TRUE(jbooleans);
244
245 for (size_t i = 0; i < kLen; ++i) {
246 jboolean j = static_cast<jboolean>(kBools[i]);
247 env->SetBooleanArrayRegion(jbooleans.obj(), i, 1, &j);
248 ASSERT_FALSE(HasException(env));
249 }
250
251 std::vector<bool> bools;
252 JavaBooleanArrayToBoolVector(env, jbooleans, &bools);
253
254 ASSERT_EQ(static_cast<jsize>(bools.size()),
255 env->GetArrayLength(jbooleans.obj()));
256
257 CheckBoolArrayConversion(env, jbooleans, bools, kLen);
258 }
259
TEST(JniArray,JavaIntArrayToIntVector)260 TEST(JniArray, JavaIntArrayToIntVector) {
261 const int kInts[] = {0, 1, -1};
262 const size_t kLen = std::size(kInts);
263
264 JNIEnv* env = AttachCurrentThread();
265 ScopedJavaLocalRef<jintArray> jints(env, env->NewIntArray(kLen));
266 ASSERT_TRUE(jints);
267
268 for (size_t i = 0; i < kLen; ++i) {
269 jint j = static_cast<jint>(kInts[i]);
270 env->SetIntArrayRegion(jints.obj(), i, 1, &j);
271 ASSERT_FALSE(HasException(env));
272 }
273
274 std::vector<int> ints;
275 JavaIntArrayToIntVector(env, jints, &ints);
276
277 ASSERT_EQ(static_cast<jsize>(ints.size()), env->GetArrayLength(jints.obj()));
278
279 CheckIntArrayConversion(env, jints, ints, kLen);
280 }
281
TEST(JniArray,JavaLongArrayToInt64Vector)282 TEST(JniArray, JavaLongArrayToInt64Vector) {
283 const int64_t kInt64s[] = {0LL, 1LL, -1LL};
284 const size_t kLen = std::size(kInt64s);
285
286 JNIEnv* env = AttachCurrentThread();
287 ScopedJavaLocalRef<jlongArray> jlongs(env, env->NewLongArray(kLen));
288 ASSERT_TRUE(jlongs);
289
290 for (size_t i = 0; i < kLen; ++i) {
291 jlong j = static_cast<jlong>(kInt64s[i]);
292 env->SetLongArrayRegion(jlongs.obj(), i, 1, &j);
293 ASSERT_FALSE(HasException(env));
294 }
295
296 std::vector<int64_t> int64s;
297 JavaLongArrayToInt64Vector(env, jlongs, &int64s);
298
299 ASSERT_EQ(static_cast<jsize>(int64s.size()),
300 env->GetArrayLength(jlongs.obj()));
301
302 jlong value;
303 for (size_t i = 0; i < kLen; ++i) {
304 env->GetLongArrayRegion(jlongs.obj(), i, 1, &value);
305 ASSERT_EQ(int64s[i], value);
306 ASSERT_EQ(kInt64s[i], int64s[i]);
307 }
308 }
309
TEST(JniArray,JavaLongArrayToLongVector)310 TEST(JniArray, JavaLongArrayToLongVector) {
311 const int64_t kInt64s[] = {0LL, 1LL, -1LL};
312 const size_t kLen = std::size(kInt64s);
313
314 JNIEnv* env = AttachCurrentThread();
315 ScopedJavaLocalRef<jlongArray> jlongs(env, env->NewLongArray(kLen));
316 ASSERT_TRUE(jlongs);
317
318 for (size_t i = 0; i < kLen; ++i) {
319 jlong j = static_cast<jlong>(kInt64s[i]);
320 env->SetLongArrayRegion(jlongs.obj(), i, 1, &j);
321 ASSERT_FALSE(HasException(env));
322 }
323
324 std::vector<jlong> jlongs_vector;
325 JavaLongArrayToLongVector(env, jlongs, &jlongs_vector);
326
327 ASSERT_EQ(static_cast<jsize>(jlongs_vector.size()),
328 env->GetArrayLength(jlongs.obj()));
329
330 jlong value;
331 for (size_t i = 0; i < kLen; ++i) {
332 env->GetLongArrayRegion(jlongs.obj(), i, 1, &value);
333 ASSERT_EQ(jlongs_vector[i], value);
334 }
335 }
336
TEST(JniArray,JavaFloatArrayToFloatVector)337 TEST(JniArray, JavaFloatArrayToFloatVector) {
338 const float kFloats[] = {0.0, 0.5, -0.5};
339 const size_t kLen = std::size(kFloats);
340
341 JNIEnv* env = AttachCurrentThread();
342 ScopedJavaLocalRef<jfloatArray> jfloats(env, env->NewFloatArray(kLen));
343 ASSERT_TRUE(jfloats);
344
345 for (size_t i = 0; i < kLen; ++i) {
346 jfloat j = static_cast<jfloat>(kFloats[i]);
347 env->SetFloatArrayRegion(jfloats.obj(), i, 1, &j);
348 ASSERT_FALSE(HasException(env));
349 }
350
351 std::vector<float> floats;
352 JavaFloatArrayToFloatVector(env, jfloats, &floats);
353
354 ASSERT_EQ(static_cast<jsize>(floats.size()),
355 env->GetArrayLength(jfloats.obj()));
356
357 jfloat value;
358 for (size_t i = 0; i < kLen; ++i) {
359 env->GetFloatArrayRegion(jfloats.obj(), i, 1, &value);
360 ASSERT_EQ(floats[i], value);
361 }
362 }
363
TEST(JniArray,JavaDoubleArrayToDoubleVector)364 TEST(JniArray, JavaDoubleArrayToDoubleVector) {
365 const std::vector<double> kDoubles = {0.0, 0.5, -0.5,
366 std::numeric_limits<double>::min()};
367 JNIEnv* env = AttachCurrentThread();
368 ScopedJavaLocalRef<jdoubleArray> jdoubles(
369 env, env->NewDoubleArray(kDoubles.size()));
370 ASSERT_TRUE(jdoubles);
371
372 env->SetDoubleArrayRegion(jdoubles.obj(), 0, kDoubles.size(),
373 reinterpret_cast<const jdouble*>(kDoubles.data()));
374 ASSERT_FALSE(HasException(env));
375
376 std::vector<double> doubles;
377 JavaDoubleArrayToDoubleVector(env, jdoubles, &doubles);
378 ASSERT_EQ(kDoubles, doubles);
379 }
380
TEST(JniArray,JavaArrayOfByteArrayToStringVector)381 TEST(JniArray, JavaArrayOfByteArrayToStringVector) {
382 const int kMaxItems = 50;
383 JNIEnv* env = AttachCurrentThread();
384
385 // Create a byte[][] object.
386 ScopedJavaLocalRef<jclass> byte_array_clazz(env, env->FindClass("[B"));
387 ASSERT_TRUE(byte_array_clazz);
388
389 ScopedJavaLocalRef<jobjectArray> array(
390 env, env->NewObjectArray(kMaxItems, byte_array_clazz.obj(), NULL));
391 ASSERT_TRUE(array);
392
393 // Create kMaxItems byte buffers.
394 char text[16];
395 for (int i = 0; i < kMaxItems; ++i) {
396 snprintf(text, sizeof text, "%d", i);
397 ScopedJavaLocalRef<jbyteArray> byte_array =
398 ToJavaByteArray(env, reinterpret_cast<uint8_t*>(text),
399 static_cast<size_t>(strlen(text)));
400 ASSERT_TRUE(byte_array);
401
402 env->SetObjectArrayElement(array.obj(), i, byte_array.obj());
403 ASSERT_FALSE(HasException(env));
404 }
405
406 // Convert to std::vector<std::string>, check the content.
407 std::vector<std::string> vec;
408 JavaArrayOfByteArrayToStringVector(env, array, &vec);
409
410 EXPECT_EQ(static_cast<size_t>(kMaxItems), vec.size());
411 for (int i = 0; i < kMaxItems; ++i) {
412 snprintf(text, sizeof text, "%d", i);
413 EXPECT_STREQ(text, vec[i].c_str());
414 }
415 }
416
TEST(JniArray,JavaArrayOfByteArrayToBytesVector)417 TEST(JniArray, JavaArrayOfByteArrayToBytesVector) {
418 const size_t kMaxItems = 50;
419 const uint8_t kStep = 37;
420 JNIEnv* env = AttachCurrentThread();
421
422 // Create a byte[][] object.
423 ScopedJavaLocalRef<jclass> byte_array_clazz(env, env->FindClass("[B"));
424 ASSERT_TRUE(byte_array_clazz);
425
426 ScopedJavaLocalRef<jobjectArray> array(
427 env, env->NewObjectArray(kMaxItems, byte_array_clazz.obj(), nullptr));
428 ASSERT_TRUE(array);
429
430 // Create kMaxItems byte buffers with size |i|+1 on each step;
431 std::vector<std::vector<uint8_t>> input_bytes;
432 input_bytes.reserve(kMaxItems);
433 for (size_t i = 0; i < kMaxItems; ++i) {
434 std::vector<uint8_t> cur_bytes(i + 1);
435 for (size_t j = 0; j < cur_bytes.size(); ++j)
436 cur_bytes[j] = static_cast<uint8_t>(i + j * kStep);
437 ScopedJavaLocalRef<jbyteArray> byte_array =
438 ToJavaByteArray(env, cur_bytes.data(), cur_bytes.size());
439 ASSERT_TRUE(byte_array);
440
441 env->SetObjectArrayElement(array.obj(), i, byte_array.obj());
442 ASSERT_FALSE(HasException(env));
443
444 input_bytes.push_back(std::move(cur_bytes));
445 }
446 ASSERT_EQ(kMaxItems, input_bytes.size());
447
448 // Convert to std::vector<std::vector<uint8_t>>, check the content.
449 std::vector<std::vector<uint8_t>> result;
450 JavaArrayOfByteArrayToBytesVector(env, array, &result);
451
452 EXPECT_EQ(input_bytes.size(), result.size());
453 for (size_t i = 0; i < kMaxItems; ++i)
454 EXPECT_THAT(result[i], ::testing::ElementsAreArray(input_bytes.at(i)));
455 }
456
TEST(JniArray,JavaArrayOfStringArrayToVectorOfStringVector)457 TEST(JniArray, JavaArrayOfStringArrayToVectorOfStringVector) {
458 const std::vector<std::vector<std::u16string>> kArrays = {
459 {u"a", u"f"}, {u"a", u""}, {}, {u""}};
460
461 JNIEnv* env = AttachCurrentThread();
462
463 ScopedJavaLocalRef<jobjectArray> array(
464 env, env->NewObjectArray(kArrays.size(),
465 env->FindClass("[Ljava/lang/String;"), NULL));
466 ASSERT_TRUE(array);
467
468 ScopedJavaLocalRef<jclass> string_clazz(env,
469 env->FindClass("java/lang/String"));
470 ASSERT_TRUE(string_clazz);
471
472 for (size_t i = 0; i < kArrays.size(); ++i) {
473 const std::vector<std::u16string>& child_data = kArrays[i];
474
475 ScopedJavaLocalRef<jobjectArray> child_array(
476 env, env->NewObjectArray(child_data.size(), string_clazz.obj(), NULL));
477 ASSERT_TRUE(child_array);
478
479 for (size_t j = 0; j < child_data.size(); ++j) {
480 ScopedJavaLocalRef<jstring> item =
481 base::android::ConvertUTF16ToJavaString(env, child_data[j]);
482 env->SetObjectArrayElement(child_array.obj(), j, item.obj());
483 ASSERT_FALSE(HasException(env));
484 }
485 env->SetObjectArrayElement(array.obj(), i, child_array.obj());
486 }
487
488 std::vector<std::vector<std::u16string>> vec;
489 Java2dStringArrayTo2dStringVector(env, array, &vec);
490
491 ASSERT_EQ(kArrays, vec);
492 }
493
TEST(JniArray,JavaArrayOfIntArrayToIntVector)494 TEST(JniArray, JavaArrayOfIntArrayToIntVector) {
495 const size_t kNumItems = 4;
496 JNIEnv* env = AttachCurrentThread();
497
498 // Create an int[][] object.
499 ScopedJavaLocalRef<jclass> int_array_clazz(env, env->FindClass("[I"));
500 ASSERT_TRUE(int_array_clazz);
501
502 ScopedJavaLocalRef<jobjectArray> array(
503 env, env->NewObjectArray(kNumItems, int_array_clazz.obj(), nullptr));
504 ASSERT_TRUE(array);
505
506 // Populate int[][] object.
507 const int kInts0[] = {0, 1, -1, std::numeric_limits<int32_t>::min(),
508 std::numeric_limits<int32_t>::max()};
509 const size_t kLen0 = std::size(kInts0);
510 ScopedJavaLocalRef<jintArray> int_array0 = ToJavaIntArray(env, kInts0, kLen0);
511 env->SetObjectArrayElement(array.obj(), 0, int_array0.obj());
512
513 const int kInts1[] = {3, 4, 5};
514 const size_t kLen1 = std::size(kInts1);
515 ScopedJavaLocalRef<jintArray> int_array1 = ToJavaIntArray(env, kInts1, kLen1);
516 env->SetObjectArrayElement(array.obj(), 1, int_array1.obj());
517
518 const int kInts2[] = {};
519 const size_t kLen2 = 0;
520 ScopedJavaLocalRef<jintArray> int_array2 = ToJavaIntArray(env, kInts2, kLen2);
521 env->SetObjectArrayElement(array.obj(), 2, int_array2.obj());
522
523 const int kInts3[] = {16};
524 const size_t kLen3 = std::size(kInts3);
525 ScopedJavaLocalRef<jintArray> int_array3 = ToJavaIntArray(env, kInts3, kLen3);
526 env->SetObjectArrayElement(array.obj(), 3, int_array3.obj());
527
528 // Convert to std::vector<std::vector<int>>, check the content.
529 std::vector<std::vector<int>> out;
530 JavaArrayOfIntArrayToIntVector(env, array, &out);
531
532 EXPECT_EQ(kNumItems, out.size());
533 CheckIntArrayConversion(env, int_array0, out[0], kLen0);
534 CheckIntArrayConversion(env, int_array1, out[1], kLen1);
535 CheckIntArrayConversion(env, int_array2, out[2], kLen2);
536 CheckIntArrayConversion(env, int_array3, out[3], kLen3);
537 }
538
TEST(JniArray,ToJavaArrayOfObjectsOfClass)539 TEST(JniArray, ToJavaArrayOfObjectsOfClass) {
540 JNIEnv* env = AttachCurrentThread();
541
542 std::vector<ScopedJavaLocalRef<jobject>> objects = {
543 ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "one")),
544 ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "two")),
545 ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "three")),
546 };
547
548 ScopedJavaLocalRef<jobjectArray> j_array =
549 ToJavaArrayOfObjects(env, jni_zero::g_string_class, objects);
550 ASSERT_TRUE(j_array);
551
552 EXPECT_EQ("one",
553 ConvertJavaStringToUTF8(
554 env, ScopedJavaLocalRef<jstring>(
555 env, static_cast<jstring>(env->GetObjectArrayElement(
556 j_array.obj(), 0)))));
557 EXPECT_EQ("two",
558 ConvertJavaStringToUTF8(
559 env, ScopedJavaLocalRef<jstring>(
560 env, static_cast<jstring>(env->GetObjectArrayElement(
561 j_array.obj(), 1)))));
562 EXPECT_EQ("three",
563 ConvertJavaStringToUTF8(
564 env, ScopedJavaLocalRef<jstring>(
565 env, static_cast<jstring>(env->GetObjectArrayElement(
566 j_array.obj(), 2)))));
567 }
568
TEST(JniArray,ToJavaArrayOfObjectLocalRef)569 TEST(JniArray, ToJavaArrayOfObjectLocalRef) {
570 JNIEnv* env = AttachCurrentThread();
571
572 std::vector<ScopedJavaLocalRef<jobject>> objects = {
573 ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "one")),
574 ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "two")),
575 ScopedJavaLocalRef<jobject>(ConvertUTF8ToJavaString(env, "three")),
576 };
577
578 ScopedJavaLocalRef<jobjectArray> j_array = ToJavaArrayOfObjects(env, objects);
579 ASSERT_TRUE(j_array);
580
581 EXPECT_EQ("one",
582 ConvertJavaStringToUTF8(
583 env, ScopedJavaLocalRef<jstring>(
584 env, static_cast<jstring>(env->GetObjectArrayElement(
585 j_array.obj(), 0)))));
586 EXPECT_EQ("two",
587 ConvertJavaStringToUTF8(
588 env, ScopedJavaLocalRef<jstring>(
589 env, static_cast<jstring>(env->GetObjectArrayElement(
590 j_array.obj(), 1)))));
591 EXPECT_EQ("three",
592 ConvertJavaStringToUTF8(
593 env, ScopedJavaLocalRef<jstring>(
594 env, static_cast<jstring>(env->GetObjectArrayElement(
595 j_array.obj(), 2)))));
596 }
597
TEST(JniArray,ToJavaArrayOfObjectGlobalRef)598 TEST(JniArray, ToJavaArrayOfObjectGlobalRef) {
599 JNIEnv* env = AttachCurrentThread();
600
601 std::vector<ScopedJavaGlobalRef<jobject>> objects = {
602 ScopedJavaGlobalRef<jobject>(ConvertUTF8ToJavaString(env, "one")),
603 ScopedJavaGlobalRef<jobject>(ConvertUTF8ToJavaString(env, "two")),
604 ScopedJavaGlobalRef<jobject>(ConvertUTF8ToJavaString(env, "three")),
605 };
606
607 ScopedJavaLocalRef<jobjectArray> j_array = ToJavaArrayOfObjects(env, objects);
608 ASSERT_TRUE(j_array);
609
610 EXPECT_EQ("one",
611 ConvertJavaStringToUTF8(
612 env, ScopedJavaLocalRef<jstring>(
613 env, static_cast<jstring>(env->GetObjectArrayElement(
614 j_array.obj(), 0)))));
615 EXPECT_EQ("two",
616 ConvertJavaStringToUTF8(
617 env, ScopedJavaLocalRef<jstring>(
618 env, static_cast<jstring>(env->GetObjectArrayElement(
619 j_array.obj(), 1)))));
620 EXPECT_EQ("three",
621 ConvertJavaStringToUTF8(
622 env, ScopedJavaLocalRef<jstring>(
623 env, static_cast<jstring>(env->GetObjectArrayElement(
624 j_array.obj(), 2)))));
625 }
626 } // namespace base::android
627