xref: /aosp_15_r20/external/fbjni/test/jni/primitive_array_tests.cpp (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cmath>
18 #include <vector>
19 
20 #include <fbjni/fbjni.h>
21 
22 #include "expect.h"
23 
24 using namespace facebook::jni;
25 
testMakeBoolArray(alias_ref<jclass>,jint size)26 local_ref<jbooleanArray> testMakeBoolArray(alias_ref<jclass>, jint size) {
27   return make_boolean_array(size);
28 }
29 
testMakeByteArray(alias_ref<jclass>,jint size)30 local_ref<jbyteArray> testMakeByteArray(alias_ref<jclass>, jint size) {
31   return make_byte_array(size);
32 }
33 
testMakeCharArray(alias_ref<jclass>,jint size)34 local_ref<jcharArray> testMakeCharArray(alias_ref<jclass>, jint size) {
35   return make_char_array(size);
36 }
37 
testMakeShortArray(alias_ref<jclass>,jint size)38 local_ref<jshortArray> testMakeShortArray(alias_ref<jclass>, jint size) {
39   return make_short_array(size);
40 }
41 
testMakeIntArray(alias_ref<jclass>,jint size)42 local_ref<jintArray> testMakeIntArray(alias_ref<jclass>, jint size) {
43   return make_int_array(size);
44 }
45 
testMakeLongArray(alias_ref<jclass>,jint size)46 local_ref<jlongArray> testMakeLongArray(alias_ref<jclass>, jint size) {
47   return make_long_array(size);
48 }
49 
testMakeFloatArray(alias_ref<jclass>,jint size)50 local_ref<jfloatArray> testMakeFloatArray(alias_ref<jclass>, jint size) {
51   return make_float_array(size);
52 }
53 
testMakeDoubleArray(alias_ref<jclass>,jint size)54 local_ref<jdoubleArray> testMakeDoubleArray(alias_ref<jclass>, jint size) {
55   return make_double_array(size);
56 }
57 
testGetSetBooleanArray(alias_ref<jclass>,alias_ref<jbooleanArray> array)58 jboolean testGetSetBooleanArray(
59     alias_ref<jclass>,
60     alias_ref<jbooleanArray> array) {
61   EXPECT(array);
62 
63   auto n = array->size();
64   EXPECT(n == 2);
65 
66   auto vec = std::vector<jboolean>(n);
67   array->getRegion(0, n, vec.data());
68   auto smartbuf = array->getRegion(0, n);
69 
70   EXPECT(!vec[0] && vec[1]);
71   EXPECT(!smartbuf[0] && smartbuf[1]);
72 
73   for (auto i = 0u; i < n; ++i) {
74     smartbuf[i] = !smartbuf[i];
75   }
76 
77   array->setRegion(0, n, smartbuf.get());
78 
79   return JNI_TRUE;
80 }
81 
testPinBooleanArray(alias_ref<jclass>,alias_ref<jbooleanArray> array)82 jboolean testPinBooleanArray(
83     alias_ref<jclass>,
84     alias_ref<jbooleanArray> array) {
85   EXPECT(array);
86 
87   auto n = static_cast<jboolean>(array->size());
88   auto pinned = array->pin();
89 
90   EXPECT(!pinned[0] && pinned[1]);
91 
92   for (auto i = 0; i < n; ++i) {
93     pinned[i] = !pinned[i];
94   }
95 
96   return JNI_TRUE;
97 }
98 
99 constexpr double kEps = 1e-3;
100 
101 template <typename JArrayType>
testGetSetArray(alias_ref<jclass>,alias_ref<JArrayType> array)102 jboolean testGetSetArray(alias_ref<jclass>, alias_ref<JArrayType> array) {
103   EXPECT(array);
104   int n = array->size();
105   auto vec = std::vector<typename jtype_traits<JArrayType>::entry_type>(n);
106   array->getRegion(0, n, vec.data());
107   auto smartbuf = array->getRegion(0, n);
108 
109   for (auto i = 0; i < n; ++i) {
110     EXPECT(std::abs(static_cast<double>(vec[i] - i)) < kEps);
111     EXPECT(std::abs(static_cast<double>(smartbuf[i] - i)) < kEps);
112   }
113 
114   for (auto i = 0; i < n; ++i) {
115     smartbuf[i] *= 2;
116   }
117 
118   array->setRegion(0, n, smartbuf.get());
119 
120   return JNI_TRUE;
121 }
122 
123 template <typename JArrayType>
testPinArray(alias_ref<jclass>,alias_ref<JArrayType> array)124 jboolean testPinArray(alias_ref<jclass>, alias_ref<JArrayType> array) {
125   EXPECT(array);
126 
127   int n = array->size();
128   auto pinned = array->pin();
129 
130   for (auto i = 0; i < n; ++i) {
131     EXPECT(std::abs(static_cast<double>(pinned[i] - i)) < kEps);
132   }
133 
134   for (auto i = 0; i < n; ++i) {
135     pinned[i] *= 2;
136   }
137 
138   return JNI_TRUE;
139 }
140 
141 template <typename JArrayType>
testPinArrayRegion(alias_ref<jclass>,alias_ref<JArrayType> array)142 jboolean testPinArrayRegion(alias_ref<jclass>, alias_ref<JArrayType> array) {
143   EXPECT(array);
144   EXPECT(array->size() > 5);
145 
146   int splits[] = {0, 1, 3, static_cast<int>(array->size())};
147   for (int i = 0; i < 3; i++) {
148     auto pinned = array->pinRegion(splits[i], splits[i + 1] - splits[i]);
149     for (int j = 0; j < static_cast<int>(pinned.size()); j++) {
150       EXPECT(std::abs(static_cast<double>(pinned[j] - j - splits[i])) < kEps);
151       pinned[j] *= 2;
152     }
153   }
154   return JNI_TRUE;
155 }
156 
157 template <typename JArrayType>
testPinArrayCritical(alias_ref<jclass>,alias_ref<JArrayType> array)158 jboolean testPinArrayCritical(alias_ref<jclass>, alias_ref<JArrayType> array) {
159   EXPECT(array);
160 
161   int n = array->size();
162   auto pinned = array->pinCritical();
163 
164   for (auto i = 0; i < n; ++i) {
165     EXPECT(std::abs(static_cast<double>(pinned[i] - i)) < kEps);
166   }
167 
168   for (auto i = 0; i < n; ++i) {
169     pinned[i] *= 2;
170   }
171 
172   return JNI_TRUE;
173 }
174 
testIndexOutOfBoundsInRegions(alias_ref<jclass>)175 jboolean testIndexOutOfBoundsInRegions(alias_ref<jclass>) {
176   constexpr auto N = 7;
177   constexpr auto TOO_MUCH = 10;
178   constexpr auto NEGATIVE = -1;
179 
180   auto array = make_int_array(N);
181 
182   try {
183     auto buf = array->getRegion(TOO_MUCH, N);
184     EXPECT(false);
185   } catch (JniException&) {
186   }
187 
188   try {
189     auto buf = array->getRegion(NEGATIVE, N);
190     EXPECT(false);
191   } catch (JniException&) {
192   }
193 
194   try {
195     auto vec = std::vector<jint>(TOO_MUCH);
196     array->setRegion(0, vec.size(), vec.data());
197     EXPECT(false);
198   } catch (JniException&) {
199   }
200 
201   try {
202     auto vec = std::vector<jint>(1);
203     array->setRegion(NEGATIVE, vec.size(), vec.data());
204     EXPECT(false);
205   } catch (JniException&) {
206   }
207 
208   return JNI_TRUE;
209 }
210 
TestBooleanArrayIndexing(alias_ref<jobject> self,alias_ref<jbooleanArray> input,jint idx)211 jboolean TestBooleanArrayIndexing(
212     alias_ref<jobject> self,
213     alias_ref<jbooleanArray> input,
214     jint idx) {
215   auto array = input->pin();
216   jboolean value = array[idx];
217   return value;
218 }
219 
TestIntegerArrayIndexing(alias_ref<jobject> self,alias_ref<jintArray> input,jint idx)220 jint TestIntegerArrayIndexing(
221     alias_ref<jobject> self,
222     alias_ref<jintArray> input,
223     jint idx) {
224   auto array = input->pin();
225   jint value = array[idx];
226   return value;
227 }
228 
TestIntegerArraySize(alias_ref<jobject> self,alias_ref<jintArray> input)229 jsize TestIntegerArraySize(
230     alias_ref<jobject> self,
231     alias_ref<jintArray> input) {
232   auto array = input->pin();
233   jsize size = array.size();
234   return size;
235 }
236 
TestIntegerArrayIncrement(alias_ref<jobject> self,alias_ref<jintArray> input)237 alias_ref<jintArray> TestIntegerArrayIncrement(
238     alias_ref<jobject> self,
239     alias_ref<jintArray> input) {
240   auto array = input->pin();
241   for (size_t ii = 0; ii < array.size(); ii++) {
242     array[ii]++;
243   }
244   return input;
245 }
246 
TestIntegerArrayMoveAssignment(alias_ref<jobject> self,alias_ref<jintArray> input)247 void TestIntegerArrayMoveAssignment(
248     alias_ref<jobject> self,
249     alias_ref<jintArray> input) {
250   auto array = input->pin();
251   array[0] = 0;
252   array.release();
253 }
254 
isPinnedArrayACopy(alias_ref<jobject>,alias_ref<jintArray> input)255 jboolean isPinnedArrayACopy(alias_ref<jobject>, alias_ref<jintArray> input) {
256   return input->pin().isCopy();
257 }
258 
testCopiedPinnedArray(alias_ref<jobject>,alias_ref<jintArray> input)259 jboolean testCopiedPinnedArray(alias_ref<jobject>, alias_ref<jintArray> input) {
260   EXPECT(input->size() > 0);
261   input->pin()[0] = 100;
262   auto pin = input->pin();
263   EXPECT(pin.isCopy());
264   EXPECT(pin[0] == input->pin()[0]);
265 
266   pin[0] = 200;
267   EXPECT(input->pin()[0] == 100);
268 
269   pin.commit();
270   EXPECT(input->pin()[0] == 200);
271   pin[0] = 300;
272   EXPECT(input->pin()[0] == 200);
273   pin.abort();
274   EXPECT(input->pin()[0] == 200);
275   pin = input->pin();
276   pin[0] = 400;
277   pin.release();
278   EXPECT(input->pin()[0] == 400);
279   return JNI_TRUE;
280 }
281 
testNonCopiedPinnedArray(alias_ref<jobject>,alias_ref<jintArray> input)282 jboolean testNonCopiedPinnedArray(
283     alias_ref<jobject>,
284     alias_ref<jintArray> input) {
285   EXPECT(input->size() > 0);
286   auto pin = input->pin();
287   EXPECT(!pin.isCopy());
288   EXPECT(pin[0] == input->pin()[0]);
289   pin.commit();
290   EXPECT(pin[0] == input->pin()[0]);
291   pin[0] = 100;
292   EXPECT(pin[0] == input->pin()[0]);
293   input->pin()[0] = 200;
294   EXPECT(pin[0] == input->pin()[0]);
295   pin.abort();
296   return JNI_TRUE;
297 }
298 
RegisterPrimitiveArrayTests()299 void RegisterPrimitiveArrayTests() {
300   registerNatives(
301       "com/facebook/jni/PrimitiveArrayTests",
302       {
303           makeNativeMethod("nativeTestMakeBooleanArray", testMakeBoolArray),
304           makeNativeMethod("nativeTestMakeByteArray", testMakeByteArray),
305           makeNativeMethod("nativeTestMakeCharArray", testMakeCharArray),
306           makeNativeMethod("nativeTestMakeShortArray", testMakeShortArray),
307           makeNativeMethod("nativeTestMakeIntArray", testMakeIntArray),
308           makeNativeMethod("nativeTestMakeLongArray", testMakeLongArray),
309           makeNativeMethod("nativeTestMakeFloatArray", testMakeFloatArray),
310           makeNativeMethod("nativeTestMakeDoubleArray", testMakeDoubleArray),
311 
312           makeNativeMethod(
313               "nativeTestGetSetBooleanArray", testGetSetBooleanArray),
314           makeNativeMethod(
315               "nativeTestGetSetByteArray", testGetSetArray<jbyteArray>),
316           makeNativeMethod(
317               "nativeTestGetSetCharArray", testGetSetArray<jcharArray>),
318           makeNativeMethod(
319               "nativeTestGetSetShortArray", testGetSetArray<jshortArray>),
320           makeNativeMethod(
321               "nativeTestGetSetIntArray", testGetSetArray<jintArray>),
322           makeNativeMethod(
323               "nativeTestGetSetLongArray", testGetSetArray<jlongArray>),
324           makeNativeMethod(
325               "nativeTestGetSetFloatArray", testGetSetArray<jfloatArray>),
326           makeNativeMethod(
327               "nativeTestGetSetDoubleArray", testGetSetArray<jdoubleArray>),
328 
329           makeNativeMethod("nativeTestPinBooleanArray", testPinBooleanArray),
330           makeNativeMethod("nativeTestPinByteArray", testPinArray<jbyteArray>),
331           makeNativeMethod("nativeTestPinCharArray", testPinArray<jcharArray>),
332           makeNativeMethod(
333               "nativeTestPinShortArray", testPinArray<jshortArray>),
334           makeNativeMethod("nativeTestPinIntArray", testPinArray<jintArray>),
335           makeNativeMethod("nativeTestPinLongArray", testPinArray<jlongArray>),
336           makeNativeMethod(
337               "nativeTestPinFloatArray", testPinArray<jfloatArray>),
338           makeNativeMethod(
339               "nativeTestPinDoubleArray", testPinArray<jdoubleArray>),
340 
341           makeNativeMethod(
342               "nativeTestPinByteArrayRegion", testPinArrayRegion<jbyteArray>),
343           makeNativeMethod(
344               "nativeTestPinCharArrayRegion", testPinArrayRegion<jcharArray>),
345           makeNativeMethod(
346               "nativeTestPinShortArrayRegion", testPinArrayRegion<jshortArray>),
347           makeNativeMethod(
348               "nativeTestPinIntArrayRegion", testPinArrayRegion<jintArray>),
349           makeNativeMethod(
350               "nativeTestPinLongArrayRegion", testPinArrayRegion<jlongArray>),
351           makeNativeMethod(
352               "nativeTestPinFloatArrayRegion", testPinArrayRegion<jfloatArray>),
353           makeNativeMethod(
354               "nativeTestPinDoubleArrayRegion",
355               testPinArrayRegion<jdoubleArray>),
356 
357           makeNativeMethod(
358               "nativeTestPinByteArrayCritical",
359               testPinArrayCritical<jbyteArray>),
360           makeNativeMethod(
361               "nativeTestPinCharArrayCritical",
362               testPinArrayCritical<jcharArray>),
363           makeNativeMethod(
364               "nativeTestPinShortArrayCritical",
365               testPinArrayCritical<jshortArray>),
366           makeNativeMethod(
367               "nativeTestPinIntArrayCritical", testPinArrayCritical<jintArray>),
368           makeNativeMethod(
369               "nativeTestPinLongArrayCritical",
370               testPinArrayCritical<jlongArray>),
371           makeNativeMethod(
372               "nativeTestPinFloatArrayCritical",
373               testPinArrayCritical<jfloatArray>),
374           makeNativeMethod(
375               "nativeTestPinDoubleArrayCritical",
376               testPinArrayCritical<jdoubleArray>),
377 
378           makeNativeMethod(
379               "nativeTestIndexOutOfBoundsInRegions",
380               testIndexOutOfBoundsInRegions),
381 
382           makeNativeMethod(
383               "nativeTestBooleanArrayIndexing", TestBooleanArrayIndexing),
384           makeNativeMethod(
385               "nativeTestIntegerArrayIndexing", TestIntegerArrayIndexing),
386           makeNativeMethod("nativeTestIntegerArraySize", TestIntegerArraySize),
387           makeNativeMethod(
388               "nativeTestIntegerArrayIncrement", TestIntegerArrayIncrement),
389           makeNativeMethod(
390               "nativeTestIntegerArrayMoveAssignment",
391               TestIntegerArrayMoveAssignment),
392 
393           makeNativeMethod("nativeIsPinnedArrayACopy", isPinnedArrayACopy),
394           makeNativeMethod(
395               "nativeTestCopiedPinnedArray", testCopiedPinnedArray),
396           makeNativeMethod(
397               "nativeTestNonCopiedPinnedArray", testNonCopiedPinnedArray),
398       });
399 }
400