• 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             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