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