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: ReplaceAllElements
421 * @tc.desc:
422 * @tc.type: FUNC
423 * @tc.require:
424 */
HWTEST_F_L0(JSAPIArrayListTest,ReplaceAllElements)425 HWTEST_F_L0(JSAPIArrayListTest, ReplaceAllElements)
426 {
427 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
428 auto result = ReplaceOrForEachCommon(thread, arrayList);
429 EXPECT_EQ(result.GetTaggedValue(), JSTaggedValue::Undefined());
430
431 // Recheck the results after replace.
432 uint32_t length = arrayList->GetLength().GetArrayLength();
433 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
434 for (uint32_t i = 0; i < length; i++) {
435 EXPECT_EQ(elements->Get(i), JSTaggedValue(i));
436 }
437 }
438
439 /**
440 * @tc.name: SubArrayList
441 * @tc.desc:
442 * @tc.type: FUNC
443 * @tc.require:
444 */
HWTEST_F_L0(JSAPIArrayListTest,SubArrayList)445 HWTEST_F_L0(JSAPIArrayListTest, SubArrayList)
446 {
447 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
448 uint32_t addElementNums = 256;
449 for (uint32_t i = 0; i < addElementNums; i++) {
450 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
451 JSAPIArrayList::Add(thread, arrayList, value);
452 }
453 uint32_t formIndex = 50;
454 uint32_t toIndex = 100;
455 JSHandle<JSTaggedValue> fromIndexValue(thread, JSTaggedValue(formIndex));
456 JSHandle<JSTaggedValue> toIndexValue(thread, JSTaggedValue(toIndex));
457 JSTaggedValue subArrayListValue =
458 JSAPIArrayList::SubArrayList(thread, arrayList, fromIndexValue, toIndexValue);
459 JSHandle<JSAPIArrayList> subArrayList(thread, subArrayListValue);
460 JSHandle<TaggedArray> subElements(thread, subArrayList->GetElements());
461 for (uint32_t i = 0; i < subArrayList->GetLength().GetArrayLength(); i++) {
462 // The element value interval of substring is [50, 100]
463 EXPECT_EQ(subElements->Get(i), JSTaggedValue(i + formIndex));
464 }
465
466 // throw error test
467 uint32_t smallIndex = -1;
468 uint32_t bigIndex = arrayList->GetLength().GetArrayLength() + 10;
469 uint32_t zeroIndex = 0;
470 JSHandle<JSTaggedValue> smallIndexValue(thread, JSTaggedValue(smallIndex));
471 JSHandle<JSTaggedValue> bigIndexValue(thread, JSTaggedValue(bigIndex));
472 JSHandle<JSTaggedValue> zeroIndexValue(thread, JSTaggedValue(zeroIndex));
473
474 // fromIndex < 0
475 JSAPIArrayList::SubArrayList(thread, arrayList, smallIndexValue, zeroIndexValue);
476 EXPECT_EXCEPTION();
477
478 // fromIndex > size
479 JSAPIArrayList::SubArrayList(thread, arrayList, bigIndexValue, zeroIndexValue);
480 EXPECT_EXCEPTION();
481
482 // toIndex <= fromIndex
483 JSAPIArrayList::SubArrayList(thread, arrayList, zeroIndexValue, zeroIndexValue);
484 EXPECT_EXCEPTION();
485
486 // toIndex < 0
487 JSAPIArrayList::SubArrayList(thread, arrayList, zeroIndexValue, smallIndexValue);
488 EXPECT_EXCEPTION();
489
490 // toIndex > length
491 JSAPIArrayList::SubArrayList(thread, arrayList, zeroIndexValue, bigIndexValue);
492 EXPECT_EXCEPTION();
493
494 // newLength == 0
495 uint32_t arrayLength = arrayList->GetLength().GetArrayLength();
496 JSHandle<JSTaggedValue> fromIndexValue0(thread, JSTaggedValue(arrayLength - 1));
497 JSHandle<JSTaggedValue> toIndexValue0(thread, JSTaggedValue(arrayLength));
498 JSTaggedValue newSubArrayListValue =
499 JSAPIArrayList::SubArrayList(thread, arrayList, fromIndexValue0, toIndexValue0);
500 JSHandle<JSAPIArrayList> newSubArrayList(thread, newSubArrayListValue);
501 int newLength = static_cast<int>(newSubArrayList->GetLength().GetArrayLength());
502 EXPECT_EQ(newLength, 1);
503 }
504
505 /**
506 * @tc.name: ForEach
507 * @tc.desc:
508 * @tc.type: FUNC
509 * @tc.require:
510 */
HWTEST_F_L0(JSAPIArrayListTest,ForEach)511 HWTEST_F_L0(JSAPIArrayListTest, ForEach)
512 {
513 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
514 auto result = ReplaceOrForEachCommon(thread, arrayList, true);
515 EXPECT_EQ(result.GetTaggedValue(), JSTaggedValue::Undefined());
516 }
517
518 /**
519 * @tc.name: GetIteratorObj
520 * @tc.desc:
521 * @tc.type: FUNC
522 * @tc.require:
523 */
HWTEST_F_L0(JSAPIArrayListTest,GetIteratorObj)524 HWTEST_F_L0(JSAPIArrayListTest, GetIteratorObj)
525 {
526 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
527 JSHandle<JSTaggedValue> iteratorObj(thread, JSAPIArrayList::GetIteratorObj(thread, arrayList));
528 EXPECT_TRUE(iteratorObj->IsJSAPIArrayListIterator());
529 }
530
531 /**
532 * @tc.name: Get & Set & Has
533 * @tc.desc:
534 * @tc.type: FUNC
535 * @tc.require:
536 */
HWTEST_F_L0(JSAPIArrayListTest,Get_Set_Has)537 HWTEST_F_L0(JSAPIArrayListTest, Get_Set_Has)
538 {
539 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
540
541 // test Has of empty arraylist
542 EXPECT_FALSE(arrayList->Has(JSTaggedValue(0)));
543
544 uint32_t elementsNum = 256;
545 for (uint32_t i = 0; i < elementsNum; i++) {
546 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
547 JSAPIArrayList::Add(thread, arrayList, value);
548 arrayList->Set(thread, i, JSTaggedValue(i * 10));
549
550 JSHandle<JSTaggedValue> getValue(thread, arrayList->Get(thread, i));
551 EXPECT_EQ(getValue.GetTaggedValue(), JSTaggedValue(i * 10));
552
553 bool isHas = arrayList->Has(JSTaggedValue(i * 10));
554 EXPECT_EQ(isHas, true);
555 EXPECT_FALSE(arrayList->Has(JSTaggedValue(-(i + 1))));
556 }
557
558 // test Get exception
559 JSTaggedValue result = arrayList->Get(thread, elementsNum);
560 EXPECT_EQ(result, JSTaggedValue::Exception());
561 EXPECT_EXCEPTION();
562
563 // test Set exception
564 JSTaggedValue result2 = arrayList->Set(thread, elementsNum, JSTaggedValue(elementsNum));
565 EXPECT_EQ(result2, JSTaggedValue::Exception());
566 EXPECT_EXCEPTION();
567 }
568
569 /**
570 * @tc.name: OwnKeys
571 * @tc.desc:
572 * @tc.type: FUNC
573 * @tc.require:
574 */
HWTEST_F_L0(JSAPIArrayListTest,OwnKeys)575 HWTEST_F_L0(JSAPIArrayListTest, OwnKeys)
576 {
577 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
578 uint32_t elementsNum = 256;
579 for (uint32_t i = 0; i < elementsNum; i++) {
580 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
581 JSAPIArrayList::Add(thread, arrayList, value);
582 }
583 JSHandle<TaggedArray> keys = JSAPIArrayList::OwnKeys(thread, arrayList);
584 uint32_t length = arrayList->GetLength().GetArrayLength();
585 for (uint32_t i = 0; i < length; i++) {
586 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
587 EcmaString::Cast(keys->Get(i).GetTaggedObject())));
588 }
589 }
590
591 /**
592 * @tc.name: GetOwnProperty
593 * @tc.desc:
594 * @tc.type: FUNC
595 * @tc.require:
596 */
HWTEST_F_L0(JSAPIArrayListTest,GetOwnProperty)597 HWTEST_F_L0(JSAPIArrayListTest, GetOwnProperty)
598 {
599 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
600 uint32_t elementsNums = 256;
601 for (uint32_t i = 0; i < elementsNums; i++) {
602 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
603 JSAPIArrayList::Add(thread, arrayList, value);
604 }
605 for (uint32_t i = 0; i < elementsNums; i++) {
606 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
607 bool getOwnPropertyRes = JSAPIArrayList::GetOwnProperty(thread, arrayList, key);
608 EXPECT_EQ(getOwnPropertyRes, true);
609 }
610
611 // test GetOwnProperty exception
612 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(elementsNums * 2));
613 EXPECT_FALSE(JSAPIArrayList::GetOwnProperty(thread, arrayList, key));
614 EXPECT_EXCEPTION();
615
616 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
617 EXPECT_FALSE(JSAPIArrayList::GetOwnProperty(thread, arrayList, undefined));
618 EXPECT_EXCEPTION();
619 }
620
621 /**
622 * @tc.name: GetProperty
623 * @tc.desc:
624 * @tc.type: FUNC
625 * @tc.require:
626 */
HWTEST_F_L0(JSAPIArrayListTest,GetProperty)627 HWTEST_F_L0(JSAPIArrayListTest, GetProperty)
628 {
629 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
630 uint32_t elementsNums = 8;
631 for (uint32_t i = 0; i < elementsNums; i++) {
632 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
633 JSAPIArrayList::Add(thread, arrayList, value);
634 }
635 for (uint32_t i = 0; i < elementsNums; i++) {
636 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
637 OperationResult getPropertyRes = JSAPIArrayList::GetProperty(thread, arrayList, key);
638 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
639 }
640 }
641
642 /**
643 * @tc.name: SetProperty
644 * @tc.desc:
645 * @tc.type: FUNC
646 * @tc.require:
647 */
HWTEST_F_L0(JSAPIArrayListTest,SetProperty)648 HWTEST_F_L0(JSAPIArrayListTest, SetProperty)
649 {
650 JSHandle<JSAPIArrayList> arrayList(thread, CreateArrayList());
651 uint32_t elementsNums = 8;
652 for (uint32_t i = 0; i < elementsNums; i++) {
653 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
654 JSAPIArrayList::Add(thread, arrayList, value);
655 }
656 for (uint32_t i = 0; i < elementsNums; i++) {
657 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
658 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
659 bool setPropertyRes = JSAPIArrayList::SetProperty(thread, arrayList, key, value);
660 EXPECT_EQ(setPropertyRes, true);
661 }
662 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
663 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
664 EXPECT_FALSE(JSAPIArrayList::SetProperty(thread, arrayList, key, value));
665 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
666 EXPECT_FALSE(JSAPIArrayList::SetProperty(thread, arrayList, key1, value));
667 }
668 } // namespace panda::test
669