1 /*
2 * Copyright (c) 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 "ecmascript/containers/containers_private.h"
17 #include "ecmascript/containers/containers_errors.h"
18 #include "ecmascript/ecma_vm.h"
19 #include "ecmascript/ecma_runtime_call_info.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/js_api/js_api_arraylist.h"
22 #include "ecmascript/global_env.h"
23 #include "ecmascript/object_factory.h"
24 #include "ecmascript/tests/ecma_test_common.h"
25
26 using namespace panda;
27 using namespace panda::ecmascript;
28
29 namespace panda::test {
30 class JSAPIArrayListTest : public BaseTestWithScope<false> {
31 public:
32 class TestClass : public base::BuiltinsBase {
33 public:
TestForEachAndReplaceAllFunc(EcmaRuntimeCallInfo * argv)34 static JSTaggedValue TestForEachAndReplaceAllFunc(EcmaRuntimeCallInfo *argv)
35 {
36 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
37 JSHandle<JSTaggedValue> key = GetCallArg(argv, 1);
38 JSHandle<JSTaggedValue> arrayList = GetCallArg(argv, 2); // 2 means the secode arg
39 if (!arrayList->IsUndefined()) {
40 if (value->IsNumber()) {
41 TaggedArray *elements = TaggedArray::Cast(JSAPIArrayList::Cast(arrayList.GetTaggedValue().
42 GetTaggedObject())->GetElements().GetTaggedObject());
43 JSTaggedValue result = elements->Get(key->GetInt());
44 EXPECT_EQ(result, value.GetTaggedValue());
45 }
46 }
47 return JSTaggedValue::True();
48 }
49 };
50
ReplaceOrForEachCommon(JSThread * thread,JSHandle<JSAPIArrayList> & arrayList,bool forEach=false)51 static JSHandle<JSTaggedValue> ReplaceOrForEachCommon(JSThread* thread, JSHandle<JSAPIArrayList>& arrayList,
52 bool forEach = false)
53 {
54 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
55 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
56 JSHandle<JSFunction> func =
57 factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForEachAndReplaceAllFunc));
58
59 auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
60 callInfo->SetFunction(JSTaggedValue::Undefined());
61 callInfo->SetThis(arrayList.GetTaggedValue());
62 callInfo->SetCallArg(0, func.GetTaggedValue());
63
64 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
65 JSTaggedValue val;
66 if (forEach) {
67 val =
68 JSAPIArrayList::ForEach(thread, callInfo->GetThis(), callInfo->GetFunction(), callInfo->GetCallArg(0));
69 } else {
70 val = JSAPIArrayList::ReplaceAllElements(thread, callInfo->GetThis(), callInfo->GetFunction(),
71 callInfo->GetCallArg(0));
72 }
73
74 JSHandle<JSTaggedValue> result(thread, val);
75 TestHelper::TearDownFrame(thread, prev);
76 return result;
77 }
78
79 protected:
CreateArrayList()80 JSAPIArrayList *CreateArrayList()
81 {
82 return EcmaContainerCommon::CreateArrayList(thread);
83 }
84 };
85
HWTEST_F_L0(JSAPIArrayListTest,CreateArrayList)86 HWTEST_F_L0(JSAPIArrayListTest, CreateArrayList)
87 {
88 JSAPIArrayList *arrayList = CreateArrayList();
89 EXPECT_TRUE(arrayList != nullptr);
90 }
91
92 /**
93 * @tc.name: Add
94 * @tc.desc:
95 * @tc.type: FUNC
96 * @tc.require:
97 */
HWTEST_F_L0(JSAPIArrayListTest,Add)98 HWTEST_F_L0(JSAPIArrayListTest, Add)
99 {
100 uint32_t increasedLength = 5;
101 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
102 for (uint32_t i = 0; i < increasedLength; i++) {
103 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 10));
104 JSAPIArrayList::Add(thread, arrayList, value);
105 }
106 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
107 for (uint32_t i = 0; i < increasedLength; i++) {
108 EXPECT_EQ(elements->Get(i), JSTaggedValue(i * 10));
109 }
110 }
111
112 /**
113 * @tc.name: Insert
114 * @tc.desc:
115 * @tc.type: FUNC
116 * @tc.require:
117 */
HWTEST_F_L0(JSAPIArrayListTest,Insert)118 HWTEST_F_L0(JSAPIArrayListTest, Insert)
119 {
120 uint32_t basicLength = 5;
121 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
122 for (uint32_t i = 0; i < basicLength; i++) {
123 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 10));
124 JSAPIArrayList::Add(thread, arrayList, value);
125 }
126 uint32_t insertStartFrom = 2;
127 uint32_t insertNums = 3;
128 for (uint32_t i = 0; i < insertNums; i++) {
129 JSHandle<JSTaggedValue> insertValue(thread, JSTaggedValue(99 + i));
130 JSAPIArrayList::Insert(thread, arrayList, insertValue, insertStartFrom + i);
131 }
132 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
133 for (uint32_t i = 0; i < basicLength + insertNums; i++) {
134 if (i < insertStartFrom) {
135 EXPECT_EQ(elements->Get(i), JSTaggedValue(i * 10));
136 } else if (i >= insertStartFrom && i < insertStartFrom + insertNums) {
137 EXPECT_EQ(elements->Get(i), JSTaggedValue(99 + i - insertStartFrom));
138 } else if (i >= insertStartFrom + insertNums) {
139 EXPECT_EQ(elements->Get(i), JSTaggedValue((i - insertNums) * 10));
140 }
141 }
142
143 // throw error
144 // index < 0
145 JSHandle<JSTaggedValue> zeroValue(thread, JSTaggedValue(0));
146 JSAPIArrayList::Insert(thread, arrayList, zeroValue, -1);
147 EXPECT_EXCEPTION();
148
149 // index > length
150 int outOfRangeNumber = basicLength + insertNums + 10;
151 JSAPIArrayList::Insert(thread, arrayList, zeroValue, outOfRangeNumber);
152 EXPECT_EXCEPTION();
153 }
154
155 /**
156 * @tc.name: Clear & IsEmpty
157 * @tc.desc:
158 * @tc.type: FUNC
159 * @tc.require:
160 */
HWTEST_F_L0(JSAPIArrayListTest,Clear)161 HWTEST_F_L0(JSAPIArrayListTest, Clear)
162 {
163 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
164 EXPECT_TRUE(JSAPIArrayList::IsEmpty(arrayList));
165 EXPECT_EQ(arrayList->GetLength(), JSTaggedValue(0));
166
167 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(99));
168 JSAPIArrayList::Add(thread, arrayList, value);
169 EXPECT_FALSE(JSAPIArrayList::IsEmpty(arrayList));
170 EXPECT_EQ(arrayList->GetLength(), JSTaggedValue(1));
171
172 JSAPIArrayList::Clear(thread, arrayList);
173 EXPECT_TRUE(JSAPIArrayList::IsEmpty(arrayList));
174 EXPECT_EQ(arrayList->GetLength(), JSTaggedValue(0));
175 }
176
177 /**
178 * @tc.name: Clone
179 * @tc.desc:
180 * @tc.type: FUNC
181 * @tc.require:
182 */
HWTEST_F_L0(JSAPIArrayListTest,Clone)183 HWTEST_F_L0(JSAPIArrayListTest, Clone)
184 {
185 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
186 uint32_t length = 10;
187 for (uint32_t i = 0; i < length; i++) {
188 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
189 JSAPIArrayList::Add(thread, arrayList, value);
190 }
191 JSHandle<JSAPIArrayList> newArrayList = JSAPIArrayList::Clone(thread, arrayList);
192 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
193 JSHandle<TaggedArray> newElements(thread, newArrayList->GetElements());
194 for (uint32_t i = 0; i < length; i++) {
195 EXPECT_EQ(elements->Get(i), JSTaggedValue(i));
196 EXPECT_EQ(newElements->Get(i), JSTaggedValue(i));
197 }
198 }
199
GetCapacityCommon(JSThread * thread,JSHandle<JSAPIArrayList> & arrayList,uint32_t addElementNums,uint32_t & currentCapacity)200 static uint32_t GetCapacityCommon(JSThread* thread, JSHandle<JSAPIArrayList>& arrayList, uint32_t addElementNums,
201 uint32_t& currentCapacity)
202 {
203 uint32_t growCapacityTimes = 0;
204 for (uint32_t i = 0; i < addElementNums; i++) {
205 JSAPIArrayList::Add(thread, arrayList, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
206
207 // After capacity expansion, the capacity will be about 1.5 times that of the original.
208 currentCapacity = JSAPIArrayList::DEFAULT_CAPACITY_LENGTH;
209 for (uint32_t j = 0; j < growCapacityTimes; j++) {
210 currentCapacity = static_cast<uint32_t>(currentCapacity * 1.5); // 1.5: cap
211 }
212 EXPECT_EQ(JSAPIArrayList::GetCapacity(thread, arrayList), currentCapacity);
213
214 // When an element is added to the end of the current list, dynamic capacity expansion will be triggered.
215 if (i == (currentCapacity - 2U)) {
216 growCapacityTimes++;
217 }
218 }
219
220 // Expand capacity to a specified capacity value
221 uint32_t newCapacity = JSAPIArrayList::GetCapacity(thread, arrayList);
222 return newCapacity;
223 }
224
225 /**
226 * @tc.name: GetCapacity & IncreaseCapacityTo
227 * @tc.desc:
228 * @tc.type: FUNC
229 * @tc.require:
230 */
HWTEST_F_L0(JSAPIArrayListTest,GetCapacity_IncreaseCapacityTo)231 HWTEST_F_L0(JSAPIArrayListTest, GetCapacity_IncreaseCapacityTo)
232 {
233 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
234 uint32_t addElementNums = 256;
235 uint32_t currentCapacity = JSAPIArrayList::DEFAULT_CAPACITY_LENGTH;
236 uint32_t oldCapacity = JSAPIArrayList::GetCapacity(thread, arrayList);
237 EXPECT_EQ(oldCapacity, JSAPIArrayList::DEFAULT_CAPACITY_LENGTH);
238 auto newCapacity = GetCapacityCommon(thread, arrayList, addElementNums, currentCapacity);
239 EXPECT_EQ(newCapacity, currentCapacity);
240
241 JSAPIArrayList::IncreaseCapacityTo(thread, arrayList, currentCapacity + 1230U);
242 newCapacity = JSAPIArrayList::GetCapacity(thread, arrayList);
243 EXPECT_EQ(newCapacity, currentCapacity + 1230U);
244 }
245
246 /**
247 * @tc.name: TrimToCurrentLength
248 * @tc.desc:
249 * @tc.type: FUNC
250 * @tc.require:
251 */
HWTEST_F_L0(JSAPIArrayListTest,TrimToCurrentLength)252 HWTEST_F_L0(JSAPIArrayListTest, TrimToCurrentLength)
253 {
254 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
255 uint32_t addElementNums = 256;
256 uint32_t currentCapacity = JSAPIArrayList::DEFAULT_CAPACITY_LENGTH;
257 auto newCapacity = GetCapacityCommon(thread, arrayList, addElementNums, currentCapacity);
258 EXPECT_EQ(newCapacity, currentCapacity);
259
260 // Cut the excess length to the actual number of elements
261 JSAPIArrayList::TrimToCurrentLength(thread, arrayList);
262 EXPECT_EQ(JSAPIArrayList::GetCapacity(thread, arrayList), addElementNums);
263 }
264
265 /**
266 * @tc.name: GetIndexOf & GetLastIndexOf
267 * @tc.desc:
268 * @tc.type: FUNC
269 * @tc.require:
270 */
HWTEST_F_L0(JSAPIArrayListTest,GetIndexOf_GetLastIndexOf)271 HWTEST_F_L0(JSAPIArrayListTest, GetIndexOf_GetLastIndexOf)
272 {
273 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
274 uint32_t addElementNums = 100;
275 for (uint32_t i = 0; i < addElementNums; i++) {
276 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
277 JSAPIArrayList::Add(thread, arrayList, value);
278 }
279 for (uint32_t i = 0; i < JSAPIArrayList::GetCapacity(thread, arrayList); i++) {
280 if (i < addElementNums) {
281 int index =
282 JSAPIArrayList::GetIndexOf(thread, arrayList, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
283 EXPECT_EQ(index, static_cast<int>(i));
284 } else {
285 int index =
286 JSAPIArrayList::GetIndexOf(thread, arrayList, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
287 EXPECT_EQ(index, -1);
288 }
289 }
290
291 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(99));
292 JSAPIArrayList::Add(thread, arrayList, value);
293 int firstIndex =
294 JSAPIArrayList::GetIndexOf(thread, arrayList, JSHandle<JSTaggedValue>(thread, JSTaggedValue(99)));
295 EXPECT_EQ(firstIndex, 99);
296
297 int lastIndex =
298 JSAPIArrayList::GetLastIndexOf(thread, arrayList, JSHandle<JSTaggedValue>(thread, JSTaggedValue(99)));
299 EXPECT_EQ(lastIndex, 99 + 1);
300 int lastIndex1 =
301 JSAPIArrayList::GetLastIndexOf(
302 thread, arrayList, JSHandle<JSTaggedValue>(thread, JSTaggedValue(addElementNums)));
303 EXPECT_EQ(lastIndex1, -1);
304 }
305
306 /**
307 * @tc.name: RemoveByIndex & Remove
308 * @tc.desc:
309 * @tc.type: FUNC
310 * @tc.require:
311 */
HWTEST_F_L0(JSAPIArrayListTest,RemoveByIndex_Remove)312 HWTEST_F_L0(JSAPIArrayListTest, RemoveByIndex_Remove)
313 {
314 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
315 uint32_t addElementNums = 256;
316 uint32_t removeElementNums = 56;
317 for (uint32_t i = 0; i < addElementNums; i++) {
318 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
319 JSAPIArrayList::Add(thread, arrayList, value);
320 }
321
322 // RemoveByIndex
323 {
324 for (uint32_t i = 0; i < removeElementNums; i++) {
325 // Delete elements with indexes between [0, 55].
326 JSAPIArrayList::RemoveByIndex(thread, arrayList, 0);
327 }
328 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
329 for (uint32_t i = 0; i < addElementNums - removeElementNums; i++) {
330 // The value of the corresponding index [0, 199] is [56, 255].
331 EXPECT_EQ(elements->Get(i), JSTaggedValue(i + removeElementNums));
332 }
333 }
334
335 // Remove
336 {
337 for (uint32_t i = removeElementNums; i < 100; i++) {
338 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
339
340 // Delete 44 elements whose element values are in [56, 99].
341 JSAPIArrayList::Remove(thread, arrayList, value);
342 }
343 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
344 for (uint32_t i = 0; i < addElementNums - 100 - 1; i++) {
345
346 // The value of the corresponding index [0, 155] is [100, 255].
347 EXPECT_EQ(elements->Get(i), JSTaggedValue(i + 100));
348 }
349 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(addElementNums));
350 bool result = JSAPIArrayList::Remove(thread, arrayList, value);
351 EXPECT_FALSE(result);
352 }
353 }
354
355 /**
356 * @tc.name: RemoveByRange
357 * @tc.desc:
358 * @tc.type: FUNC
359 * @tc.require:
360 */
HWTEST_F_L0(JSAPIArrayListTest,RemoveByRange)361 HWTEST_F_L0(JSAPIArrayListTest, RemoveByRange)
362 {
363 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
364 uint32_t addElementNums = 150;
365 for (uint32_t i = 0; i < addElementNums; i++) {
366 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
367 JSAPIArrayList::Add(thread, arrayList, value);
368 }
369 // RemoveByRange
370 {
371 uint32_t formIndex = 50;
372 uint32_t toIndex = 100;
373 JSHandle<JSTaggedValue> fromIndexValue(thread, JSTaggedValue(formIndex));
374 JSHandle<JSTaggedValue> toIndexValue(thread, JSTaggedValue(toIndex));
375
376 // Remove the value between 50 and 100 of the index element.
377 JSAPIArrayList::RemoveByRange(thread, arrayList, fromIndexValue, toIndexValue);
378 uint32_t length = arrayList->GetLength().GetArrayLength();
379 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
380 for (uint32_t i = 0; i < length - (toIndex - formIndex); i++) {
381 // The value of the corresponding index [0, 100] is [0, 49] ∪ [100, 149].
382 if (i >= 0 && i < 50) {
383 EXPECT_EQ(elements->Get(i), JSTaggedValue(i));
384 } else if (i > 50) {
385 EXPECT_EQ(elements->Get(i), JSTaggedValue(i + 50));
386 }
387 }
388
389 // throw error test
390 uint32_t smallIndex = -1;
391 uint32_t bigIndex = arrayList->GetLength().GetArrayLength() + 10;
392 uint32_t zeroIndex = 0;
393 JSHandle<JSTaggedValue> smallIndexValue(thread, JSTaggedValue(smallIndex));
394 JSHandle<JSTaggedValue> bigIndexValue(thread, JSTaggedValue(bigIndex));
395 JSHandle<JSTaggedValue> zeroIndexValue(thread, JSTaggedValue(zeroIndex));
396
397 // startIndex < 0
398 JSAPIArrayList::RemoveByRange(thread, arrayList, smallIndexValue, zeroIndexValue);
399 EXPECT_EXCEPTION();
400
401 // startIndex >= size
402 JSAPIArrayList::RemoveByRange(thread, arrayList, bigIndexValue, zeroIndexValue);
403 EXPECT_EXCEPTION();
404
405 // endIndex <= startIndex
406 JSAPIArrayList::RemoveByRange(thread, arrayList, zeroIndexValue, zeroIndexValue);
407 EXPECT_EXCEPTION();
408
409 // endIndex < 0
410 JSAPIArrayList::RemoveByRange(thread, arrayList, zeroIndexValue, smallIndexValue);
411 EXPECT_EXCEPTION();
412
413 // endIndex > length
414 JSAPIArrayList::RemoveByRange(thread, arrayList, zeroIndexValue, bigIndexValue);
415 EXPECT_EXCEPTION();
416 }
417 }
418
419 /**
420 * @tc.name: RemoveByRange and GetHeapUsedSize
421 * @tc.desc:
422 * @tc.type: FUNC
423 * @tc.require:
424 */
HWTEST_F_L0(JSAPIArrayListTest,RemoveByRangeAndGetHeapUsedSize)425 HWTEST_F_L0(JSAPIArrayListTest, RemoveByRangeAndGetHeapUsedSize)
426 {
427 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
428 uint32_t addElementNums = 10; // 10: elements size
429 for (uint32_t i = 0; i < addElementNums; i++) {
430 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
431 JSAPIArrayList::Add(thread, arrayList, value);
432 }
433 JSHandle<JSTaggedValue> fromIndexValue(thread, JSTaggedValue(1)); // 1: start index
434 JSHandle<JSTaggedValue> toIndexValue(thread, JSTaggedValue(3)); // 3: end index
435 JSAPIArrayList::RemoveByRange(thread, arrayList, fromIndexValue, toIndexValue);
436 // test heap is normal after RemoveByRange, GetLiveObjectSize will iterate heap
437 instance->GetHeap()->GetLiveObjectSize();
438 EXPECT_EQ(arrayList->GetLength().GetInt(), 8); // 8: new length
439 }
440
441 /**
442 * @tc.name: ReplaceAllElements
443 * @tc.desc:
444 * @tc.type: FUNC
445 * @tc.require:
446 */
HWTEST_F_L0(JSAPIArrayListTest,ReplaceAllElements)447 HWTEST_F_L0(JSAPIArrayListTest, ReplaceAllElements)
448 {
449 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
450 auto result = ReplaceOrForEachCommon(thread, arrayList);
451 EXPECT_EQ(result.GetTaggedValue(), JSTaggedValue::Undefined());
452
453 // Recheck the results after replace.
454 uint32_t length = arrayList->GetLength().GetArrayLength();
455 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
456 for (uint32_t i = 0; i < length; i++) {
457 EXPECT_EQ(elements->Get(i), JSTaggedValue(i));
458 }
459 }
460
461 /**
462 * @tc.name: SubArrayList
463 * @tc.desc:
464 * @tc.type: FUNC
465 * @tc.require:
466 */
HWTEST_F_L0(JSAPIArrayListTest,SubArrayList)467 HWTEST_F_L0(JSAPIArrayListTest, SubArrayList)
468 {
469 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
470 uint32_t addElementNums = 256;
471 for (uint32_t i = 0; i < addElementNums; i++) {
472 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
473 JSAPIArrayList::Add(thread, arrayList, value);
474 }
475 uint32_t formIndex = 50;
476 uint32_t toIndex = 100;
477 JSHandle<JSTaggedValue> fromIndexValue(thread, JSTaggedValue(formIndex));
478 JSHandle<JSTaggedValue> toIndexValue(thread, JSTaggedValue(toIndex));
479 JSTaggedValue subArrayListValue =
480 JSAPIArrayList::SubArrayList(thread, arrayList, fromIndexValue, toIndexValue);
481 JSHandle<JSAPIArrayList> subArrayList(thread, subArrayListValue);
482 JSHandle<TaggedArray> subElements(thread, subArrayList->GetElements());
483 for (uint32_t i = 0; i < subArrayList->GetLength().GetArrayLength(); i++) {
484 // The element value interval of substring is [50, 100]
485 EXPECT_EQ(subElements->Get(i), JSTaggedValue(i + formIndex));
486 }
487
488 // throw error test
489 uint32_t smallIndex = -1;
490 uint32_t bigIndex = arrayList->GetLength().GetArrayLength() + 10;
491 uint32_t zeroIndex = 0;
492 JSHandle<JSTaggedValue> smallIndexValue(thread, JSTaggedValue(smallIndex));
493 JSHandle<JSTaggedValue> bigIndexValue(thread, JSTaggedValue(bigIndex));
494 JSHandle<JSTaggedValue> zeroIndexValue(thread, JSTaggedValue(zeroIndex));
495
496 // fromIndex < 0
497 JSAPIArrayList::SubArrayList(thread, arrayList, smallIndexValue, zeroIndexValue);
498 EXPECT_EXCEPTION();
499
500 // fromIndex > size
501 JSAPIArrayList::SubArrayList(thread, arrayList, bigIndexValue, zeroIndexValue);
502 EXPECT_EXCEPTION();
503
504 // toIndex <= fromIndex
505 JSAPIArrayList::SubArrayList(thread, arrayList, zeroIndexValue, zeroIndexValue);
506 EXPECT_EXCEPTION();
507
508 // toIndex < 0
509 JSAPIArrayList::SubArrayList(thread, arrayList, zeroIndexValue, smallIndexValue);
510 EXPECT_EXCEPTION();
511
512 // toIndex > length
513 JSAPIArrayList::SubArrayList(thread, arrayList, zeroIndexValue, bigIndexValue);
514 EXPECT_EXCEPTION();
515
516 // newLength == 0
517 uint32_t arrayLength = arrayList->GetLength().GetArrayLength();
518 JSHandle<JSTaggedValue> fromIndexValue0(thread, JSTaggedValue(arrayLength - 1));
519 JSHandle<JSTaggedValue> toIndexValue0(thread, JSTaggedValue(arrayLength));
520 JSTaggedValue newSubArrayListValue =
521 JSAPIArrayList::SubArrayList(thread, arrayList, fromIndexValue0, toIndexValue0);
522 JSHandle<JSAPIArrayList> newSubArrayList(thread, newSubArrayListValue);
523 int newLength = static_cast<int>(newSubArrayList->GetLength().GetArrayLength());
524 EXPECT_EQ(newLength, 1);
525 }
526
527 /**
528 * @tc.name: ForEach
529 * @tc.desc:
530 * @tc.type: FUNC
531 * @tc.require:
532 */
HWTEST_F_L0(JSAPIArrayListTest,ForEach)533 HWTEST_F_L0(JSAPIArrayListTest, ForEach)
534 {
535 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
536 auto result = ReplaceOrForEachCommon(thread, arrayList, true);
537 EXPECT_EQ(result.GetTaggedValue(), JSTaggedValue::Undefined());
538 }
539
540 /**
541 * @tc.name: GetIteratorObj
542 * @tc.desc:
543 * @tc.type: FUNC
544 * @tc.require:
545 */
HWTEST_F_L0(JSAPIArrayListTest,GetIteratorObj)546 HWTEST_F_L0(JSAPIArrayListTest, GetIteratorObj)
547 {
548 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
549 JSHandle<JSTaggedValue> iteratorObj(thread, JSAPIArrayList::GetIteratorObj(thread, arrayList));
550 EXPECT_TRUE(iteratorObj->IsJSAPIArrayListIterator());
551 }
552
553 /**
554 * @tc.name: Get & Set & Has
555 * @tc.desc:
556 * @tc.type: FUNC
557 * @tc.require:
558 */
HWTEST_F_L0(JSAPIArrayListTest,Get_Set_Has)559 HWTEST_F_L0(JSAPIArrayListTest, Get_Set_Has)
560 {
561 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
562
563 // test Has of empty arraylist
564 EXPECT_FALSE(arrayList->Has(JSTaggedValue(0)));
565
566 uint32_t elementsNum = 256;
567 for (uint32_t i = 0; i < elementsNum; i++) {
568 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
569 JSAPIArrayList::Add(thread, arrayList, value);
570 arrayList->Set(thread, i, JSTaggedValue(i * 10));
571
572 JSHandle<JSTaggedValue> getValue(thread, arrayList->Get(thread, i));
573 EXPECT_EQ(getValue.GetTaggedValue(), JSTaggedValue(i * 10));
574
575 bool isHas = arrayList->Has(JSTaggedValue(i * 10));
576 EXPECT_EQ(isHas, true);
577 EXPECT_FALSE(arrayList->Has(JSTaggedValue(-(i + 1))));
578 }
579
580 // test Get exception
581 JSTaggedValue result = arrayList->Get(thread, elementsNum);
582 EXPECT_EQ(result, JSTaggedValue::Exception());
583 EXPECT_EXCEPTION();
584
585 // test Set exception
586 JSTaggedValue result2 = arrayList->Set(thread, elementsNum, JSTaggedValue(elementsNum));
587 EXPECT_EQ(result2, JSTaggedValue::Exception());
588 EXPECT_EXCEPTION();
589 }
590
591 /**
592 * @tc.name: OwnKeys
593 * @tc.desc:
594 * @tc.type: FUNC
595 * @tc.require:
596 */
HWTEST_F_L0(JSAPIArrayListTest,OwnKeys)597 HWTEST_F_L0(JSAPIArrayListTest, OwnKeys)
598 {
599 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
600 uint32_t elementsNum = 256;
601 for (uint32_t i = 0; i < elementsNum; i++) {
602 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
603 JSAPIArrayList::Add(thread, arrayList, value);
604 }
605 JSHandle<TaggedArray> keys = JSAPIArrayList::OwnKeys(thread, arrayList);
606 uint32_t length = arrayList->GetLength().GetArrayLength();
607 for (uint32_t i = 0; i < length; i++) {
608 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
609 EcmaString::Cast(keys->Get(i).GetTaggedObject())));
610 }
611 }
612
613 /**
614 * @tc.name: GetOwnProperty
615 * @tc.desc:
616 * @tc.type: FUNC
617 * @tc.require:
618 */
HWTEST_F_L0(JSAPIArrayListTest,GetOwnProperty)619 HWTEST_F_L0(JSAPIArrayListTest, GetOwnProperty)
620 {
621 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
622 uint32_t elementsNums = 256;
623 for (uint32_t i = 0; i < elementsNums; i++) {
624 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
625 JSAPIArrayList::Add(thread, arrayList, value);
626 }
627 for (uint32_t i = 0; i < elementsNums; i++) {
628 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
629 bool getOwnPropertyRes = JSAPIArrayList::GetOwnProperty(thread, arrayList, key);
630 EXPECT_EQ(getOwnPropertyRes, true);
631 }
632
633 // test GetOwnProperty exception
634 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(elementsNums * 2));
635 EXPECT_FALSE(JSAPIArrayList::GetOwnProperty(thread, arrayList, key));
636 EXPECT_EXCEPTION();
637
638 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
639 EXPECT_FALSE(JSAPIArrayList::GetOwnProperty(thread, arrayList, undefined));
640 EXPECT_EXCEPTION();
641 }
642
643 /**
644 * @tc.name: GetProperty
645 * @tc.desc:
646 * @tc.type: FUNC
647 * @tc.require:
648 */
HWTEST_F_L0(JSAPIArrayListTest,GetProperty)649 HWTEST_F_L0(JSAPIArrayListTest, GetProperty)
650 {
651 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
652 uint32_t elementsNums = 8;
653 for (uint32_t i = 0; i < elementsNums; i++) {
654 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
655 JSAPIArrayList::Add(thread, arrayList, value);
656 }
657 for (uint32_t i = 0; i < elementsNums; i++) {
658 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
659 OperationResult getPropertyRes = JSAPIArrayList::GetProperty(thread, arrayList, key);
660 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
661 }
662 }
663
664 /**
665 * @tc.name: SetProperty
666 * @tc.desc:
667 * @tc.type: FUNC
668 * @tc.require:
669 */
HWTEST_F_L0(JSAPIArrayListTest,SetProperty)670 HWTEST_F_L0(JSAPIArrayListTest, SetProperty)
671 {
672 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
673 uint32_t elementsNums = 8;
674 for (uint32_t i = 0; i < elementsNums; i++) {
675 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
676 JSAPIArrayList::Add(thread, arrayList, value);
677 }
678 for (uint32_t i = 0; i < elementsNums; i++) {
679 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
680 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
681 bool setPropertyRes = JSAPIArrayList::SetProperty(thread, arrayList, key, value);
682 EXPECT_EQ(setPropertyRes, true);
683 }
684 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
685 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
686 EXPECT_FALSE(JSAPIArrayList::SetProperty(thread, arrayList, key, value));
687 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
688 EXPECT_FALSE(JSAPIArrayList::SetProperty(thread, arrayList, key1, value));
689 }
690 } // namespace panda::test
691