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