• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "plugins/ets/tests/mock/mock_test_helper.h"
17 
18 #include "runtime/include/runtime.h"
19 #include "runtime/include/runtime_options.h"
20 #include "plugins/ets/runtime/types/ets_method.h"
21 
22 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-magic-numbers)
23 
24 namespace panda::ets::test {
25 
26 class EtsNativeInterfaceArrayTest : public MockEtsNapiTestBaseClass {};
27 
TEST_F(EtsNativeInterfaceArrayTest,NewPrimitiveArrayTestEmpty)28 TEST_F(EtsNativeInterfaceArrayTest, NewPrimitiveArrayTestEmpty)
29 {
30     ets_booleanArray array1 = env_->NewBooleanArray(0);
31     ASSERT_NE(array1, nullptr);
32     ASSERT_FALSE(env_->ErrorOccurred());
33     EXPECT_EQ(env_->GetArrayLength(array1), static_cast<ets_size>(0));
34 
35     ets_byteArray array2 = env_->NewByteArray(0);
36     ASSERT_NE(array2, nullptr);
37     ASSERT_FALSE(env_->ErrorOccurred());
38     EXPECT_EQ(env_->GetArrayLength(array2), static_cast<ets_size>(0));
39 
40     ets_charArray array3 = env_->NewCharArray(0);
41     ASSERT_NE(array3, nullptr);
42     ASSERT_FALSE(env_->ErrorOccurred());
43     EXPECT_EQ(env_->GetArrayLength(array3), static_cast<ets_size>(0));
44 
45     ets_shortArray array4 = env_->NewShortArray(0);
46     ASSERT_NE(array4, nullptr);
47     ASSERT_FALSE(env_->ErrorOccurred());
48     EXPECT_EQ(env_->GetArrayLength(array4), static_cast<ets_size>(0));
49 
50     ets_intArray array5 = env_->NewIntArray(0);
51     ASSERT_NE(array5, nullptr);
52     ASSERT_FALSE(env_->ErrorOccurred());
53     EXPECT_EQ(env_->GetArrayLength(array5), static_cast<ets_size>(0));
54 
55     ets_longArray array6 = env_->NewLongArray(0);
56     ASSERT_NE(array6, nullptr);
57     ASSERT_FALSE(env_->ErrorOccurred());
58     EXPECT_EQ(env_->GetArrayLength(array6), static_cast<ets_size>(0));
59 
60     ets_floatArray array7 = env_->NewFloatArray(0);
61     ASSERT_NE(array7, nullptr);
62     ASSERT_FALSE(env_->ErrorOccurred());
63     EXPECT_EQ(env_->GetArrayLength(array7), static_cast<ets_size>(0));
64 
65     ets_doubleArray array8 = env_->NewDoubleArray(0);
66     ASSERT_NE(array8, nullptr);
67     ASSERT_FALSE(env_->ErrorOccurred());
68     EXPECT_EQ(env_->GetArrayLength(array8), static_cast<ets_size>(0));
69 }
70 
TEST_F(EtsNativeInterfaceArrayTest,BooleanArray)71 TEST_F(EtsNativeInterfaceArrayTest, BooleanArray)
72 {
73     const std::vector<ets_boolean> src = {ETS_FALSE, ETS_FALSE, ETS_FALSE, ETS_TRUE, ETS_FALSE, ETS_FALSE};
74     ets_booleanArray array = env_->NewBooleanArray(src.size());
75     ASSERT_NE(array, nullptr);
76 
77     ets_size length = env_->GetArrayLength(array);
78     ASSERT_EQ(length, src.size());
79 
80     env_->SetBooleanArrayRegion(array, 0, src.size(), src.data());
81     {
82         // Use PinBooleanArray
83         ets_boolean *buf = env_->PinBooleanArray(array);
84         ASSERT_NE(buf, nullptr);
85         std::vector<ets_boolean> res1 = {buf, buf + length};
86         ASSERT_EQ(res1, src);
87 
88         std::vector<ets_boolean> res2(src.size());
89         env_->GetBooleanArrayRegion(array, 0, src.size(), res2.data());
90         ASSERT_EQ(res2, src);
91 
92         env_->UnpinBooleanArray(array);
93     }
94     {
95         // Use GetBooleanArrayRegion
96         std::vector<ets_boolean> vec(length);
97         env_->GetBooleanArrayRegion(array, 0, length, vec.data());
98         ASSERT_EQ(vec, src);
99     }
100     {
101         // Use GetBooleanArrayRegion with shift
102         ets_size half = length / 2;
103         std::vector<ets_boolean> vec(length - half);
104         env_->GetBooleanArrayRegion(array, half, length - half, vec.data());
105         ASSERT_TRUE(std::equal(src.begin() + half, src.end(), vec.begin()));
106     }
107 }
108 
TEST_F(EtsNativeInterfaceArrayTest,ByteArray)109 TEST_F(EtsNativeInterfaceArrayTest, ByteArray)
110 {
111     const std::vector<ets_byte> src = {std::numeric_limits<ets_byte>::lowest(), -1, 0, 1,
112                                        std::numeric_limits<ets_byte>::max()};
113     ets_byteArray array = env_->NewByteArray(src.size());
114     ASSERT_NE(array, nullptr);
115 
116     ets_size length = env_->GetArrayLength(array);
117     ASSERT_EQ(length, src.size());
118 
119     env_->SetByteArrayRegion(array, 0, src.size(), src.data());
120     {
121         // Use PinByteArray
122         ets_byte *buf = env_->PinByteArray(array);
123         ASSERT_NE(buf, nullptr);
124         std::vector<ets_byte> res1 = {buf, buf + length};
125         ASSERT_EQ(res1, src);
126 
127         std::vector<ets_byte> res2(src.size());
128         env_->GetByteArrayRegion(array, 0, src.size(), res2.data());
129         ASSERT_EQ(res2, src);
130 
131         env_->UnpinByteArray(array);
132     }
133     {
134         // Use GetByteArrayRegion
135         std::vector<ets_byte> vec(length);
136         env_->GetByteArrayRegion(array, 0, length, vec.data());
137         ASSERT_EQ(vec, src);
138     }
139     {
140         // Use GetByteArrayRegion with shift
141         ets_size half = length / 2;
142         std::vector<ets_byte> vec(length - half);
143         env_->GetByteArrayRegion(array, half, length - half, vec.data());
144         ASSERT_TRUE(std::equal(src.begin() + half, src.end(), vec.begin()));
145     }
146 }
147 
TEST_F(EtsNativeInterfaceArrayTest,CharArray)148 TEST_F(EtsNativeInterfaceArrayTest, CharArray)
149 {
150     const std::vector<ets_char> src = {std::numeric_limits<ets_char>::lowest(), 0, 1, 2, 3,
151                                        std::numeric_limits<ets_char>::max()};
152     ets_charArray array = env_->NewCharArray(src.size());
153     ASSERT_NE(array, nullptr);
154 
155     ets_size length = env_->GetArrayLength(array);
156     ASSERT_EQ(length, src.size());
157 
158     env_->SetCharArrayRegion(array, 0, src.size(), src.data());
159     {
160         // Use PinCharArray
161         ets_char *buf = env_->PinCharArray(array);
162         ASSERT_NE(buf, nullptr);
163         std::vector<ets_char> res1 = {buf, buf + length};
164         ASSERT_EQ(res1, src);
165 
166         std::vector<ets_char> res2(src.size());
167         env_->GetCharArrayRegion(array, 0, src.size(), res2.data());
168         ASSERT_EQ(res2, src);
169 
170         env_->UnpinCharArray(array);
171     }
172     {
173         // Use GetCharArrayRegion
174         std::vector<ets_char> vec(length);
175         env_->GetCharArrayRegion(array, 0, length, vec.data());
176         ASSERT_EQ(vec, src);
177     }
178     {
179         // Use GetCharArrayRegion with shift
180         ets_size half = length / 2;
181         std::vector<ets_char> vec(length - half);
182         env_->GetCharArrayRegion(array, half, length - half, vec.data());
183         ASSERT_TRUE(std::equal(src.begin() + half, src.end(), vec.begin()));
184     }
185 }
186 
TEST_F(EtsNativeInterfaceArrayTest,ShortArray)187 TEST_F(EtsNativeInterfaceArrayTest, ShortArray)
188 {
189     const std::vector<ets_short> src = {std::numeric_limits<ets_short>::lowest(), -1, 0, 1,
190                                         std::numeric_limits<ets_short>::max()};
191     ets_shortArray array = env_->NewShortArray(src.size());
192     ASSERT_NE(array, nullptr);
193 
194     ets_size length = env_->GetArrayLength(array);
195     ASSERT_EQ(length, src.size());
196 
197     env_->SetShortArrayRegion(array, 0, src.size(), src.data());
198     {
199         // Use PinShortArray
200         ets_short *buf = env_->PinShortArray(array);
201         ASSERT_NE(buf, nullptr);
202         std::vector<ets_short> res1 = {buf, buf + length};
203         ASSERT_EQ(res1, src);
204 
205         std::vector<ets_short> res2(src.size());
206         env_->GetShortArrayRegion(array, 0, src.size(), res2.data());
207         ASSERT_EQ(res2, src);
208 
209         env_->UnpinShortArray(array);
210     }
211     {
212         // Use GetShortArrayRegion
213         std::vector<ets_short> vec(length);
214         env_->GetShortArrayRegion(array, 0, length, vec.data());
215         ASSERT_EQ(vec, src);
216     }
217     {
218         // Use GetShortArrayRegion with shift
219         ets_size half = length / 2;
220         std::vector<ets_short> vec(length - half);
221         env_->GetShortArrayRegion(array, half, length - half, vec.data());
222         ASSERT_TRUE(std::equal(src.begin() + half, src.end(), vec.begin()));
223     }
224 }
225 
TEST_F(EtsNativeInterfaceArrayTest,IntArray)226 TEST_F(EtsNativeInterfaceArrayTest, IntArray)
227 {
228     const std::vector<ets_int> src = {std::numeric_limits<ets_int>::lowest(), -2, -1, 0, 1, 2,
229                                       std::numeric_limits<ets_int>::max()};
230     ets_intArray array = env_->NewIntArray(src.size());
231     ASSERT_NE(array, nullptr);
232 
233     ets_size length = env_->GetArrayLength(array);
234     ASSERT_EQ(length, src.size());
235 
236     env_->SetIntArrayRegion(array, 0, src.size(), src.data());
237     {
238         // Use PinIntArray
239         ets_int *buf = env_->PinIntArray(array);
240         ASSERT_NE(buf, nullptr);
241         std::vector<ets_int> res1 = {buf, buf + length};
242         ASSERT_EQ(res1, src);
243 
244         std::vector<ets_int> res2(src.size());
245         env_->GetIntArrayRegion(array, 0, src.size(), res2.data());
246         ASSERT_EQ(res2, src);
247 
248         env_->UnpinIntArray(array);
249     }
250     {
251         // Use GetIntArrayRegion
252         std::vector<ets_int> vec(length);
253         env_->GetIntArrayRegion(array, 0, length, vec.data());
254         ASSERT_EQ(vec, src);
255     }
256     {
257         // Use GetIntArrayRegion with shift
258         ets_size half = length / 2;
259         std::vector<ets_int> vec(length - half);
260         env_->GetIntArrayRegion(array, half, length - half, vec.data());
261         ASSERT_TRUE(std::equal(src.begin() + half, src.end(), vec.begin()));
262     }
263 }
264 
TEST_F(EtsNativeInterfaceArrayTest,LongArray)265 TEST_F(EtsNativeInterfaceArrayTest, LongArray)
266 {
267     const std::vector<ets_long> src = {std::numeric_limits<ets_long>::lowest(), -1, 0, 1,
268                                        std::numeric_limits<ets_long>::max()};
269     ets_longArray array = env_->NewLongArray(src.size());
270     ASSERT_NE(array, nullptr);
271 
272     ets_size length = env_->GetArrayLength(array);
273     ASSERT_EQ(length, src.size());
274 
275     env_->SetLongArrayRegion(array, 0, src.size(), src.data());
276     {
277         // Use PinLongArray
278         ets_long *buf = env_->PinLongArray(array);
279         ASSERT_NE(buf, nullptr);
280         std::vector<ets_long> res1 = {buf, buf + length};
281         ASSERT_EQ(res1, src);
282 
283         std::vector<ets_long> res2(src.size());
284         env_->GetLongArrayRegion(array, 0, src.size(), res2.data());
285         ASSERT_EQ(res2, src);
286 
287         env_->UnpinLongArray(array);
288     }
289     {
290         // Use GetLongArrayRegion
291         std::vector<ets_long> vec(length);
292         env_->GetLongArrayRegion(array, 0, length, vec.data());
293         ASSERT_EQ(vec, src);
294     }
295     {
296         // Use GetLongArrayRegion with shift
297         ets_size half = length / 2;
298         std::vector<ets_long> vec(length - half);
299         env_->GetLongArrayRegion(array, half, length - half, vec.data());
300         ASSERT_TRUE(std::equal(src.begin() + half, src.end(), vec.begin()));
301     }
302 }
303 
TEST_F(EtsNativeInterfaceArrayTest,FloatArray)304 TEST_F(EtsNativeInterfaceArrayTest, FloatArray)
305 {
306     const std::vector<ets_float> src = {std::numeric_limits<ets_float>::lowest(), -1.0F, 0.0F, 1.0F,
307                                         std::numeric_limits<ets_float>::max()};
308     ets_floatArray array = env_->NewFloatArray(src.size());
309     ASSERT_NE(array, nullptr);
310 
311     ets_size length = env_->GetArrayLength(array);
312     ASSERT_EQ(length, src.size());
313 
314     env_->SetFloatArrayRegion(array, 0, src.size(), src.data());
315     {
316         // Use PinFloatArray
317         ets_float *buf = env_->PinFloatArray(array);
318         ASSERT_NE(buf, nullptr);
319         std::vector<ets_float> res1 = {buf, buf + length};
320         ASSERT_EQ(res1, src);
321 
322         std::vector<ets_float> res2(src.size());
323         env_->GetFloatArrayRegion(array, 0, src.size(), res2.data());
324         ASSERT_EQ(res2, src);
325 
326         env_->UnpinFloatArray(array);
327     }
328     {
329         // Use GetFloatArrayRegion
330         std::vector<ets_float> vec(length);
331         env_->GetFloatArrayRegion(array, 0, length, vec.data());
332         ASSERT_EQ(vec, src);
333     }
334     {
335         // Use GetFloatArrayRegion with shift
336         ets_size half = length / 2;
337         std::vector<ets_float> vec(length - half);
338         env_->GetFloatArrayRegion(array, half, length - half, vec.data());
339         ASSERT_TRUE(std::equal(src.begin() + half, src.end(), vec.begin()));
340     }
341 }
342 
TEST_F(EtsNativeInterfaceArrayTest,DoubleArray)343 TEST_F(EtsNativeInterfaceArrayTest, DoubleArray)
344 {
345     const std::vector<ets_double> src = {std::numeric_limits<ets_double>::lowest(), -1.1, 0, 1.1,
346                                          std::numeric_limits<ets_double>::max()};
347     ets_doubleArray array = env_->NewDoubleArray(src.size());
348     ASSERT_NE(array, nullptr);
349 
350     ets_size length = env_->GetArrayLength(array);
351     ASSERT_EQ(length, src.size());
352 
353     env_->SetDoubleArrayRegion(array, 0, src.size(), src.data());
354     {
355         // Use PinDoubleArray
356         ets_double *buf = env_->PinDoubleArray(array);
357         ASSERT_NE(buf, nullptr);
358         std::vector<ets_double> res1 = {buf, buf + length};
359         ASSERT_EQ(res1, src);
360 
361         std::vector<ets_double> res2(src.size());
362         env_->GetDoubleArrayRegion(array, 0, src.size(), res2.data());
363         ASSERT_EQ(res2, src);
364 
365         env_->UnpinDoubleArray(array);
366     }
367     {
368         // Use GetDoubleArrayRegion
369         std::vector<ets_double> vec(length);
370         env_->GetDoubleArrayRegion(array, 0, length, vec.data());
371         ASSERT_EQ(vec, src);
372     }
373     {
374         // Use GetDoubleArrayRegion with shift
375         ets_size half = length / 2;
376         std::vector<ets_double> vec(length - half);
377         env_->GetDoubleArrayRegion(array, half, length - half, vec.data());
378         ASSERT_TRUE(std::equal(src.begin() + half, src.end(), vec.begin()));
379     }
380 }
381 
TEST_F(EtsNativeInterfaceArrayTest,NewObjectsArrayZeroAndOneSize)382 TEST_F(EtsNativeInterfaceArrayTest, NewObjectsArrayZeroAndOneSize)
383 {
384     ets_class cls = env_->FindClass("std/core/String");
385     ASSERT_NE(cls, nullptr);
386     const std::string example {"sample7"};
387     ets_string str = env_->NewStringUTF(example.c_str());
388     ASSERT_NE(str, nullptr);
389 
390     ets_objectArray arrZero = env_->NewObjectsArray(0, cls, str);
391     EXPECT_EQ(env_->GetArrayLength(arrZero), static_cast<ets_size>(0));
392     ets_objectArray arrOne = env_->NewObjectsArray(1, cls, str);
393     EXPECT_EQ(env_->GetArrayLength(arrOne), static_cast<ets_size>(1));
394 }
395 
TEST_F(EtsNativeInterfaceArrayTest,NewObjectArrayTest)396 TEST_F(EtsNativeInterfaceArrayTest, NewObjectArrayTest)
397 {
398     //  NOLINTNEXTLINE(bugprone-string-literal-with-embedded-nul)
399     const std::vector<std::string> src = {"\t", "\n",       "\0",   "abcdefghijklmnopqrstuvwxyz",
400                                           "",   "texttext", "ABCD", "1111111"};
401     std::vector<ets_string> etsSrc;
402     etsSrc.reserve(src.size());
403     for (auto &s : src) {
404         etsSrc.push_back(env_->NewStringUTF(s.c_str()));
405     }
406 
407     ets_class cls = env_->FindClass("std/core/String");
408     ASSERT_NE(cls, nullptr);
409     ets_objectArray array = env_->NewObjectsArray(src.size(), cls, etsSrc[0]);
410     ASSERT_NE(array, nullptr);
411     ets_size size = env_->GetArrayLength(array);
412     ASSERT_EQ(size, src.size());
413     for (ets_size i = 1; i < size; ++i) {
414         env_->SetObjectArrayElement(array, i, etsSrc[i]);
415     }
416 
417     std::vector<std::string> etsRes;
418     etsRes.reserve(src.size());
419     for (ets_size i = 0; i < size; ++i) {
420         auto str = static_cast<ets_string>(env_->GetObjectArrayElement(array, i));
421         ets_boolean isCopy;
422         const char *res = env_->GetStringUTFChars(str, &isCopy);
423         etsRes.emplace_back(res);
424         env_->ReleaseStringUTFChars(str, res);
425     }
426     ASSERT_EQ(etsRes, src);
427 
428     panda::ets::napi::ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env_));
429     auto *objectArr = s.Convert<EtsObjectArray>(array);
430     auto *desc = objectArr->GetClass()->GetDescriptor();
431 
432     const char *expectedDesc = "[Lstd/core/String;";
433     uint32_t len = 18;
434     ASSERT_THAT(std::vector<char>(desc, desc + len), ::testing::ElementsAreArray(expectedDesc, len));
435 }
436 
437 }  // namespace panda::ets::test
438 
439 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-magic-numbers)