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_string.h"
18 #include "ecmascript/ecma_vm.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_api/js_api_vector.h"
21 #include "ecmascript/js_api/js_api_vector_iterator.h"
22 #include "ecmascript/js_function.h"
23 #include "ecmascript/js_handle.h"
24 #include "ecmascript/js_iterator.h"
25 #include "ecmascript/js_object-inl.h"
26 #include "ecmascript/js_tagged_value.h"
27 #include "ecmascript/object_factory.h"
28 #include "ecmascript/tests/ecma_test_common.h"
29
30 using namespace panda;
31
32 using namespace panda::ecmascript;
33
34 using namespace panda::ecmascript::containers;
35
36 namespace panda::test {
37 class JSAPIVectorTest : public BaseTestWithScope<false> {
38 protected:
CreateVector()39 JSAPIVector *CreateVector()
40 {
41 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
42 auto result = TestCommon::CreateContainerTaggedValue(thread, containers::ContainerTag::Vector);
43 JSHandle<JSTaggedValue> constructor(thread, result);
44 JSHandle<JSAPIVector> vector(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
45 vector->SetLength(0);
46 return *vector;
47 }
48
TestCommon(JSMutableHandle<JSTaggedValue> & value,std::string & myValue,uint32_t nums)49 JSHandle<JSAPIVector> TestCommon(JSMutableHandle<JSTaggedValue>& value, std::string& myValue, uint32_t nums)
50 {
51 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
52 JSHandle<JSAPIVector> toor(thread, CreateVector());
53
54 for (uint32_t i = 0; i < nums; i++) {
55 std::string ivalue = myValue + std::to_string(i);
56 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
57 bool result = JSAPIVector::Add(thread, toor, value);
58 EXPECT_TRUE(result);
59 EXPECT_EQ(toor->IsEmpty(), false);
60 }
61 return toor;
62 }
63 };
64
HWTEST_F_L0(JSAPIVectorTest,vectorCreate)65 HWTEST_F_L0(JSAPIVectorTest, vectorCreate)
66 {
67 JSAPIVector *vector = CreateVector();
68 EXPECT_TRUE(vector != nullptr);
69 }
70
HWTEST_F_L0(JSAPIVectorTest,AddGetHas)71 HWTEST_F_L0(JSAPIVectorTest, AddGetHas)
72 {
73 constexpr uint32_t NODE_NUMBERS = 9;
74 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
75 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
76
77 JSHandle<JSAPIVector> toor(thread, CreateVector());
78
79 // test Has of empty vector
80 value.Update(JSTaggedValue(NODE_NUMBERS));
81 EXPECT_FALSE(toor->Has(thread, value.GetTaggedValue()));
82
83 std::string myValue("myvalue");
84 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
85 std::string ivalue = myValue + std::to_string(i);
86 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
87 bool result = JSAPIVector::Add(thread, toor, value);
88 EXPECT_TRUE(result);
89 EXPECT_EQ(JSAPIVector::Get(thread, toor, i), value.GetTaggedValue());
90 EXPECT_TRUE(toor->Has(thread, value.GetTaggedValue()));
91 }
92 value.Update(JSTaggedValue(NODE_NUMBERS));
93 EXPECT_FALSE(toor->Has(thread, value.GetTaggedValue()));
94 EXPECT_EQ(static_cast<uint32_t>(toor->GetSize()), NODE_NUMBERS);
95
96 // test Get exception
97 JSAPIVector::Get(thread, toor, -1);
98 EXPECT_EXCEPTION();
99 JSAPIVector::Get(thread, toor, static_cast<int32_t>(NODE_NUMBERS));
100 EXPECT_EXCEPTION();
101
102 toor->Dump(thread);
103 }
104
HWTEST_F_L0(JSAPIVectorTest,RemoveByIndexAndRemove)105 HWTEST_F_L0(JSAPIVectorTest, RemoveByIndexAndRemove)
106 {
107 constexpr uint32_t NODE_NUMBERS = 9;
108 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
109 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
110
111 std::string myValue("myvalue");
112 auto toor = TestCommon(value, myValue, NODE_NUMBERS);
113
114 for (int32_t i = NODE_NUMBERS / 2; i > 0; i--) {
115 std::string ivalue = myValue + std::to_string(i);
116 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
117 JSTaggedValue gValue = JSAPIVector::RemoveByIndex(thread, toor, i);
118 EXPECT_EQ(gValue, value.GetTaggedValue());
119 bool delResult = JSAPIVector::Remove(thread, toor, value);
120 EXPECT_FALSE(delResult);
121 }
122
123 // test RemoveByIndex exception
124 JSTaggedValue result = JSAPIVector::RemoveByIndex(thread, toor, -1);
125 EXPECT_EQ(result, JSTaggedValue::Exception());
126 EXPECT_EXCEPTION();
127 JSTaggedValue result1 = JSAPIVector::RemoveByIndex(thread, toor, NODE_NUMBERS);
128 EXPECT_EQ(result1, JSTaggedValue::Exception());
129 EXPECT_EXCEPTION();
130
131 toor->Dump(thread);
132 }
133
HWTEST_F_L0(JSAPIVectorTest,RemoveByRangeAndGetHeapUsedSize)134 HWTEST_F_L0(JSAPIVectorTest, RemoveByRangeAndGetHeapUsedSize)
135 {
136 uint32_t NODE_NUMBERS = 9;
137 uint32_t fromIndex = 1;
138 uint32_t toIndex = 3;
139 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
140
141 std::string myValue("myvalue");
142 auto toor = TestCommon(value, myValue, NODE_NUMBERS);
143 JSAPIVector::RemoveByRange(thread, toor, fromIndex, toIndex);
144 // test heap is normal after RemoveByRange, GetLiveObjectSize will iterate heap
145 instance->GetHeap()->GetLiveObjectSize();
146 EXPECT_EQ(toor->GetLength(), static_cast<int32_t>(NODE_NUMBERS - (toIndex - fromIndex)));
147 }
148
HWTEST_F_L0(JSAPIVectorTest,ClearAndisEmpty)149 HWTEST_F_L0(JSAPIVectorTest, ClearAndisEmpty)
150 {
151 constexpr uint32_t NODE_NUMBERS = 9;
152 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
153
154 std::string myValue("myvalue");
155 auto toor = TestCommon(value, myValue, NODE_NUMBERS);
156
157 JSAPIVector::Clear(thread, toor);
158 EXPECT_EQ(toor->IsEmpty(), true);
159
160 toor->Dump(thread);
161 }
162
HWTEST_F_L0(JSAPIVectorTest,GetIndexOf)163 HWTEST_F_L0(JSAPIVectorTest, GetIndexOf)
164 {
165 constexpr uint32_t NODE_NUMBERS = 9;
166 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
167 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
168
169 JSHandle<JSAPIVector> toor(thread, CreateVector());
170
171 std::string myValue("myvalue");
172 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
173 std::string ivalue = myValue + std::to_string(i);
174 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
175 bool result = JSAPIVector::Add(thread, toor, value);
176 EXPECT_TRUE(result);
177 EXPECT_EQ(JSAPIVector::GetIndexOf(thread, toor, value), static_cast<int>(i));
178 }
179
180 toor->Dump(thread);
181 }
182
HWTEST_F_L0(JSAPIVectorTest,GetOwnProperty)183 HWTEST_F_L0(JSAPIVectorTest, GetOwnProperty)
184 {
185 constexpr uint32_t DEFAULT_LENGTH = 8;
186 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
187 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
188 JSHandle<JSAPIVector> toor(thread, CreateVector());
189
190 std::string vectorvalue("vectorvalue");
191 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
192 std::string ivalue = vectorvalue + std::to_string(i);
193 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
194 JSAPIVector::Add(thread, toor, value);
195 }
196 // test GetOwnProperty
197 int testInt = 1;
198 JSHandle<JSTaggedValue> vectorKey1(thread, JSTaggedValue(testInt));
199 EXPECT_TRUE(JSAPIVector::GetOwnProperty(thread, toor, vectorKey1));
200 testInt = 20;
201 JSHandle<JSTaggedValue> vectorKey2(thread, JSTaggedValue(testInt));
202 EXPECT_FALSE(JSAPIVector::GetOwnProperty(thread, toor, vectorKey2));
203 EXPECT_EXCEPTION();
204
205 // test GetOwnProperty exception
206 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
207 EXPECT_FALSE(JSAPIVector::GetOwnProperty(thread, toor, undefined));
208 EXPECT_EXCEPTION();
209 }
210
211 /**
212 * @tc.name: GetProperty
213 * @tc.desc:
214 * @tc.type: FUNC
215 * @tc.require:
216 */
HWTEST_F_L0(JSAPIVectorTest,GetProperty)217 HWTEST_F_L0(JSAPIVectorTest, GetProperty)
218 {
219 JSHandle<JSAPIVector> toor(thread, CreateVector());
220 uint32_t elementsNums = 8;
221 for (uint32_t i = 0; i < elementsNums; i++) {
222 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
223 JSAPIVector::Add(thread, toor, value);
224 }
225 for (uint32_t i = 0; i < elementsNums; i++) {
226 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
227 OperationResult getPropertyRes = JSAPIVector::GetProperty(thread, toor, key);
228 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
229 }
230
231 // test GetProperty exception
232 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(-1));
233 JSAPIVector::GetProperty(thread, toor, key1);
234 EXPECT_EXCEPTION();
235 JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(elementsNums));
236 JSAPIVector::GetProperty(thread, toor, key2);
237 EXPECT_EXCEPTION();
238 }
239
240 /**
241 * @tc.name: SetProperty
242 * @tc.desc:
243 * @tc.type: FUNC
244 * @tc.require:
245 */
HWTEST_F_L0(JSAPIVectorTest,SetProperty)246 HWTEST_F_L0(JSAPIVectorTest, SetProperty)
247 {
248 JSHandle<JSAPIVector> toor(thread, CreateVector());
249 uint32_t elementsNums = 8;
250 for (uint32_t i = 0; i < elementsNums; i++) {
251 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
252 JSAPIVector::Add(thread, toor, value);
253 }
254 for (uint32_t i = 0; i < elementsNums; i++) {
255 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
256 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
257 bool setPropertyRes = JSAPIVector::SetProperty(thread, toor, key, value);
258 EXPECT_EQ(setPropertyRes, true);
259 }
260 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
261 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(0));
262 EXPECT_FALSE(JSAPIVector::SetProperty(thread, toor, key, value));
263 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
264 EXPECT_FALSE(JSAPIVector::SetProperty(thread, toor, key1, value));
265 }
266
267 /**
268 * @tc.name: TrimToCurrentLength
269 * @tc.desc:
270 * @tc.type: FUNC
271 * @tc.require:
272 */
HWTEST_F_L0(JSAPIVectorTest,IncreaseCapacityToTrimToCurrentLength)273 HWTEST_F_L0(JSAPIVectorTest, IncreaseCapacityToTrimToCurrentLength)
274 {
275 JSHandle<JSAPIVector> toor(thread, CreateVector());
276 uint32_t elementsNums = 20;
277 for (uint32_t i = 0; i < elementsNums; i++) {
278 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
279 JSAPIVector::Add(thread, toor, value);
280 }
281 JSAPIVector::IncreaseCapacityTo(thread, toor, 80);
282 JSHandle<TaggedArray> elementData(thread, toor->GetElements(thread));
283 EXPECT_EQ(static_cast<int>(elementData->GetLength()), 80);
284 JSAPIVector::TrimToCurrentLength(thread, toor);
285 JSHandle<TaggedArray> newElementData(thread, toor->GetElements(thread));
286 EXPECT_EQ(newElementData->GetLength(), elementsNums);
287
288 // test IncreaseCapacityTo exception
289 JSAPIVector::IncreaseCapacityTo(thread, toor, -1);
290 EXPECT_EXCEPTION();
291 }
292
293 /**
294 * @tc.name: Insert
295 * @tc.desc:
296 * @tc.type: FUNC
297 * @tc.require:
298 */
HWTEST_F_L0(JSAPIVectorTest,Insert)299 HWTEST_F_L0(JSAPIVectorTest, Insert)
300 {
301 JSHandle<JSAPIVector> toor(thread, CreateVector());
302 uint32_t elementsNums = 20;
303 for (uint32_t i = 0; i < elementsNums; i++) {
304 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
305 JSAPIVector::Insert(thread, toor, value, 0);
306 }
307
308 // check
309 for (uint32_t i = 0; i < elementsNums; i++) {
310 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
311 EXPECT_EQ(JSAPIVector::Get(
312 thread, toor, static_cast<int32_t>(i)), JSTaggedValue(elementsNums - i - 1));
313 }
314
315 // test Insert exception
316 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(elementsNums));
317 JSAPIVector::Insert(thread, toor, value, -1);
318 EXPECT_EXCEPTION();
319
320 JSAPIVector::Insert(thread, toor, value, static_cast<int32_t>(elementsNums + 1));
321 EXPECT_EXCEPTION();
322 }
323
324 /**
325 * @tc.name: SetLength, GetIndexFrom, GetLastElement, GetLastIndexOf and GetLastIndexFrom
326 * @tc.desc:
327 * @tc.type: FUNC
328 * @tc.require:
329 */
HWTEST_F_L0(JSAPIVectorTest,SetLengthGetIndexFromGetLastElementGetLastIndexOf)330 HWTEST_F_L0(JSAPIVectorTest, SetLengthGetIndexFromGetLastElementGetLastIndexOf)
331 {
332 JSHandle<JSAPIVector> toor(thread, CreateVector());
333
334 // test GetLastElement of empty vector
335 EXPECT_EQ(toor->GetLastElement(thread), JSTaggedValue::Undefined());
336
337 // test GetLastIndexOf of empty vector
338 uint32_t elementsNums = 20;
339 JSHandle<JSTaggedValue> obj(thread, JSTaggedValue(elementsNums - 1));
340 EXPECT_EQ(JSAPIVector::GetLastIndexOf(thread, toor, obj), -1);
341
342 for (uint32_t i = 0; i < elementsNums; i++) {
343 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
344 JSAPIVector::Add(thread, toor, value);
345 }
346
347 // test GetIndexFrom
348 EXPECT_EQ(JSAPIVector::GetIndexFrom(thread, toor, obj, -1), static_cast<int32_t>(elementsNums - 1));
349
350 EXPECT_EQ(JSAPIVector::GetIndexFrom(thread, toor, obj, elementsNums), -1);
351 EXPECT_EXCEPTION();
352
353 // test GetLastElement
354 EXPECT_EQ(toor->GetLastElement(thread), JSTaggedValue(elementsNums - 1));
355
356 // test GetLastIndexOf
357 EXPECT_EQ(JSAPIVector::GetLastIndexOf(thread, toor, obj), static_cast<int32_t>(elementsNums - 1));
358
359 // test GetLastIndexFrom
360 EXPECT_EQ(JSAPIVector::GetLastIndexFrom(
361 thread, toor, obj, elementsNums - 1), static_cast<int32_t>(elementsNums - 1));
362
363 EXPECT_EQ(JSAPIVector::GetLastIndexFrom(thread, toor, obj, elementsNums), -1);
364 EXPECT_EXCEPTION();
365
366 JSHandle<JSTaggedValue> obj1(thread, JSTaggedValue(-elementsNums));
367 EXPECT_EQ(JSAPIVector::GetLastIndexFrom(thread, toor, obj1, -1), -1);
368
369 // test SetLength
370 JSAPIVector::SetLength(thread, toor, elementsNums * 3);
371 EXPECT_EQ(toor->GetLength(), static_cast<int32_t>(elementsNums * 3));
372 }
373
374 /**
375 * @tc.name: RemoveByRange
376 * @tc.desc:
377 * @tc.type: FUNC
378 * @tc.require:
379 */
HWTEST_F_L0(JSAPIVectorTest,ExceptionOfRemoveByRange)380 HWTEST_F_L0(JSAPIVectorTest, ExceptionOfRemoveByRange)
381 {
382 JSHandle<JSAPIVector> toor(thread, CreateVector());
383 uint32_t elementsNums = 20;
384 for (uint32_t i = 0; i < elementsNums; i++) {
385 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
386 JSAPIVector::Add(thread, toor, value);
387 }
388
389 // test RemoveByRange exception
390 // toIndex <= fromIndex
391 JSTaggedValue result1 = JSAPIVector::RemoveByRange(thread, toor, 0, 0);
392 EXPECT_EQ(result1, JSTaggedValue::Exception());
393 EXPECT_EXCEPTION();
394
395 // from < 0
396 JSTaggedValue result2 = JSAPIVector::RemoveByRange(thread, toor, -1, 0);
397 EXPECT_EQ(result2, JSTaggedValue::Exception());
398 EXPECT_EXCEPTION();
399
400 // fromIndex >= length
401 JSTaggedValue result3 = JSAPIVector::RemoveByRange(thread, toor, elementsNums, elementsNums * 2);
402 EXPECT_EQ(result3, JSTaggedValue::Exception());
403 EXPECT_EXCEPTION();
404 }
405
406 /**
407 * @tc.name: SubVector
408 * @tc.desc:
409 * @tc.type: FUNC
410 * @tc.require:
411 */
HWTEST_F_L0(JSAPIVectorTest,ExceptionOfSubVector)412 HWTEST_F_L0(JSAPIVectorTest, ExceptionOfSubVector)
413 {
414 JSHandle<JSAPIVector> toor(thread, CreateVector());
415 uint32_t elementsNums = 20;
416 for (uint32_t i = 0; i < elementsNums; i++) {
417 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
418 JSAPIVector::Add(thread, toor, value);
419 }
420
421 // test SubVector exception
422 // from < 0
423 JSAPIVector::SubVector(thread, toor, -1, 0);
424 EXPECT_EXCEPTION();
425
426 // toIndex < 0
427 JSAPIVector::SubVector(thread, toor, 0, -1);
428 EXPECT_EXCEPTION();
429
430 // fromIndex >= length
431 JSAPIVector::SubVector(thread, toor, elementsNums, 0);
432 EXPECT_EXCEPTION();
433
434 // ToIndex >= length
435 JSAPIVector::SubVector(thread, toor, 0, elementsNums);
436 EXPECT_EXCEPTION();
437
438 // toIndex <= fromIndex
439 JSAPIVector::SubVector(thread, toor, elementsNums - 1, 0);
440 EXPECT_EXCEPTION();
441 }
442
443 /**
444 * @tc.name: OwnKeys
445 * @tc.desc:
446 * @tc.type: FUNC
447 * @tc.require:
448 */
HWTEST_F_L0(JSAPIVectorTest,OwnKeys)449 HWTEST_F_L0(JSAPIVectorTest, OwnKeys)
450 {
451 JSHandle<JSAPIVector> toor(thread, CreateVector());
452 uint32_t elementsNums = 8;
453 for (uint32_t i = 0; i < elementsNums; i++) {
454 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
455 JSAPIVector::Add(thread, toor, value);
456 }
457 JSHandle<TaggedArray> keyArray = JSAPIVector::OwnKeys(thread, toor);
458 EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
459 EXPECT_TRUE(keyArray->GetLength() == elementsNums);
460 for (uint32_t i = 0; i < elementsNums; i++) {
461 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread,
462 *(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
463 EcmaString::Cast(keyArray->Get(thread, i).GetTaggedObject())
464 ));
465 }
466 }
467
468 /**
469 * @tc.name: GetFirstElement
470 * @tc.desc:
471 * @tc.type: FUNC
472 * @tc.require:
473 */
HWTEST_F_L0(JSAPIVectorTest,GetFirstElement)474 HWTEST_F_L0(JSAPIVectorTest, GetFirstElement)
475 {
476 JSHandle<JSAPIVector> toor(thread, CreateVector());
477 EXPECT_EQ(JSAPIVector::GetFirstElement(thread, toor), JSTaggedValue::Undefined());
478
479 uint32_t elementsNums = 8;
480 for (uint32_t i = 0; i < elementsNums; i++) {
481 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
482 JSAPIVector::Add(thread, toor, value);
483 }
484 EXPECT_EQ(JSAPIVector::GetFirstElement(thread, toor), JSTaggedValue(0));
485 }
486 } // namespace panda::test
487