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