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(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(value.GetTaggedValue()));
91 }
92 value.Update(JSTaggedValue(NODE_NUMBERS));
93 EXPECT_FALSE(toor->Has(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();
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();
132 }
133
HWTEST_F_L0(JSAPIVectorTest,ClearAndisEmpty)134 HWTEST_F_L0(JSAPIVectorTest, ClearAndisEmpty)
135 {
136 constexpr uint32_t NODE_NUMBERS = 9;
137 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
138
139 std::string myValue("myvalue");
140 auto toor = TestCommon(value, myValue, NODE_NUMBERS);
141
142 JSAPIVector::Clear(thread, toor);
143 EXPECT_EQ(toor->IsEmpty(), true);
144
145 toor->Dump();
146 }
147
HWTEST_F_L0(JSAPIVectorTest,GetIndexOf)148 HWTEST_F_L0(JSAPIVectorTest, GetIndexOf)
149 {
150 constexpr uint32_t NODE_NUMBERS = 9;
151 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
152 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
153
154 JSHandle<JSAPIVector> toor(thread, CreateVector());
155
156 std::string myValue("myvalue");
157 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
158 std::string ivalue = myValue + std::to_string(i);
159 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
160 bool result = JSAPIVector::Add(thread, toor, value);
161 EXPECT_TRUE(result);
162 EXPECT_EQ(JSAPIVector::GetIndexOf(thread, toor, value), static_cast<int>(i));
163 }
164
165 toor->Dump();
166 }
167
HWTEST_F_L0(JSAPIVectorTest,GetOwnProperty)168 HWTEST_F_L0(JSAPIVectorTest, GetOwnProperty)
169 {
170 constexpr uint32_t DEFAULT_LENGTH = 8;
171 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
172 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
173 JSHandle<JSAPIVector> toor(thread, CreateVector());
174
175 std::string vectorvalue("vectorvalue");
176 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
177 std::string ivalue = vectorvalue + std::to_string(i);
178 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
179 JSAPIVector::Add(thread, toor, value);
180 }
181 // test GetOwnProperty
182 int testInt = 1;
183 JSHandle<JSTaggedValue> vectorKey1(thread, JSTaggedValue(testInt));
184 EXPECT_TRUE(JSAPIVector::GetOwnProperty(thread, toor, vectorKey1));
185 testInt = 20;
186 JSHandle<JSTaggedValue> vectorKey2(thread, JSTaggedValue(testInt));
187 EXPECT_FALSE(JSAPIVector::GetOwnProperty(thread, toor, vectorKey2));
188 EXPECT_EXCEPTION();
189
190 // test GetOwnProperty exception
191 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
192 EXPECT_FALSE(JSAPIVector::GetOwnProperty(thread, toor, undefined));
193 EXPECT_EXCEPTION();
194 }
195
196 /**
197 * @tc.name: GetProperty
198 * @tc.desc:
199 * @tc.type: FUNC
200 * @tc.require:
201 */
HWTEST_F_L0(JSAPIVectorTest,GetProperty)202 HWTEST_F_L0(JSAPIVectorTest, GetProperty)
203 {
204 JSHandle<JSAPIVector> toor(thread, CreateVector());
205 uint32_t elementsNums = 8;
206 for (uint32_t i = 0; i < elementsNums; i++) {
207 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
208 JSAPIVector::Add(thread, toor, value);
209 }
210 for (uint32_t i = 0; i < elementsNums; i++) {
211 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
212 OperationResult getPropertyRes = JSAPIVector::GetProperty(thread, toor, key);
213 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
214 }
215
216 // test GetProperty exception
217 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(-1));
218 JSAPIVector::GetProperty(thread, toor, key1);
219 EXPECT_EXCEPTION();
220 JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(elementsNums));
221 JSAPIVector::GetProperty(thread, toor, key2);
222 EXPECT_EXCEPTION();
223 }
224
225 /**
226 * @tc.name: SetProperty
227 * @tc.desc:
228 * @tc.type: FUNC
229 * @tc.require:
230 */
HWTEST_F_L0(JSAPIVectorTest,SetProperty)231 HWTEST_F_L0(JSAPIVectorTest, SetProperty)
232 {
233 JSHandle<JSAPIVector> toor(thread, CreateVector());
234 uint32_t elementsNums = 8;
235 for (uint32_t i = 0; i < elementsNums; i++) {
236 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
237 JSAPIVector::Add(thread, toor, value);
238 }
239 for (uint32_t i = 0; i < elementsNums; i++) {
240 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
241 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
242 bool setPropertyRes = JSAPIVector::SetProperty(thread, toor, key, value);
243 EXPECT_EQ(setPropertyRes, true);
244 }
245 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
246 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(0));
247 EXPECT_FALSE(JSAPIVector::SetProperty(thread, toor, key, value));
248 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
249 EXPECT_FALSE(JSAPIVector::SetProperty(thread, toor, key1, value));
250 }
251
252 /**
253 * @tc.name: TrimToCurrentLength
254 * @tc.desc:
255 * @tc.type: FUNC
256 * @tc.require:
257 */
HWTEST_F_L0(JSAPIVectorTest,IncreaseCapacityToTrimToCurrentLength)258 HWTEST_F_L0(JSAPIVectorTest, IncreaseCapacityToTrimToCurrentLength)
259 {
260 JSHandle<JSAPIVector> toor(thread, CreateVector());
261 uint32_t elementsNums = 20;
262 for (uint32_t i = 0; i < elementsNums; i++) {
263 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
264 JSAPIVector::Add(thread, toor, value);
265 }
266 JSAPIVector::IncreaseCapacityTo(thread, toor, 80);
267 JSHandle<TaggedArray> elementData(thread, toor->GetElements());
268 EXPECT_EQ(static_cast<int>(elementData->GetLength()), 80);
269 JSAPIVector::TrimToCurrentLength(thread, toor);
270 JSHandle<TaggedArray> newElementData(thread, toor->GetElements());
271 EXPECT_EQ(newElementData->GetLength(), elementsNums);
272
273 // test IncreaseCapacityTo exception
274 JSAPIVector::IncreaseCapacityTo(thread, toor, -1);
275 EXPECT_EXCEPTION();
276 }
277
278 /**
279 * @tc.name: Insert
280 * @tc.desc:
281 * @tc.type: FUNC
282 * @tc.require:
283 */
HWTEST_F_L0(JSAPIVectorTest,Insert)284 HWTEST_F_L0(JSAPIVectorTest, Insert)
285 {
286 JSHandle<JSAPIVector> toor(thread, CreateVector());
287 uint32_t elementsNums = 20;
288 for (uint32_t i = 0; i < elementsNums; i++) {
289 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
290 JSAPIVector::Insert(thread, toor, value, 0);
291 }
292
293 // check
294 for (uint32_t i = 0; i < elementsNums; i++) {
295 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
296 EXPECT_EQ(JSAPIVector::Get(
297 thread, toor, static_cast<int32_t>(i)), JSTaggedValue(elementsNums - i - 1));
298 }
299
300 // test Insert exception
301 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(elementsNums));
302 JSAPIVector::Insert(thread, toor, value, -1);
303 EXPECT_EXCEPTION();
304
305 JSAPIVector::Insert(thread, toor, value, static_cast<int32_t>(elementsNums + 1));
306 EXPECT_EXCEPTION();
307 }
308
309 /**
310 * @tc.name: SetLength, GetIndexFrom, GetLastElement, GetLastIndexOf and GetLastIndexFrom
311 * @tc.desc:
312 * @tc.type: FUNC
313 * @tc.require:
314 */
HWTEST_F_L0(JSAPIVectorTest,SetLengthGetIndexFromGetLastElementGetLastIndexOf)315 HWTEST_F_L0(JSAPIVectorTest, SetLengthGetIndexFromGetLastElementGetLastIndexOf)
316 {
317 JSHandle<JSAPIVector> toor(thread, CreateVector());
318
319 // test GetLastElement of empty vector
320 EXPECT_EQ(toor->GetLastElement(), JSTaggedValue::Undefined());
321
322 // test GetLastIndexOf of empty vector
323 uint32_t elementsNums = 20;
324 JSHandle<JSTaggedValue> obj(thread, JSTaggedValue(elementsNums - 1));
325 EXPECT_EQ(JSAPIVector::GetLastIndexOf(thread, toor, obj), -1);
326
327 for (uint32_t i = 0; i < elementsNums; i++) {
328 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
329 JSAPIVector::Add(thread, toor, value);
330 }
331
332 // test GetIndexFrom
333 EXPECT_EQ(JSAPIVector::GetIndexFrom(thread, toor, obj, -1), static_cast<int32_t>(elementsNums - 1));
334
335 EXPECT_EQ(JSAPIVector::GetIndexFrom(thread, toor, obj, elementsNums), -1);
336 EXPECT_EXCEPTION();
337
338 // test GetLastElement
339 EXPECT_EQ(toor->GetLastElement(), JSTaggedValue(elementsNums - 1));
340
341 // test GetLastIndexOf
342 EXPECT_EQ(JSAPIVector::GetLastIndexOf(thread, toor, obj), static_cast<int32_t>(elementsNums - 1));
343
344 // test GetLastIndexFrom
345 EXPECT_EQ(JSAPIVector::GetLastIndexFrom(
346 thread, toor, obj, elementsNums - 1), static_cast<int32_t>(elementsNums - 1));
347
348 EXPECT_EQ(JSAPIVector::GetLastIndexFrom(thread, toor, obj, elementsNums), -1);
349 EXPECT_EXCEPTION();
350
351 JSHandle<JSTaggedValue> obj1(thread, JSTaggedValue(-elementsNums));
352 EXPECT_EQ(JSAPIVector::GetLastIndexFrom(thread, toor, obj1, -1), -1);
353
354 // test SetLength
355 JSAPIVector::SetLength(thread, toor, elementsNums * 3);
356 EXPECT_EQ(toor->GetLength(), static_cast<int32_t>(elementsNums * 3));
357 }
358
359 /**
360 * @tc.name: RemoveByRange
361 * @tc.desc:
362 * @tc.type: FUNC
363 * @tc.require:
364 */
HWTEST_F_L0(JSAPIVectorTest,ExceptionOfRemoveByRange)365 HWTEST_F_L0(JSAPIVectorTest, ExceptionOfRemoveByRange)
366 {
367 JSHandle<JSAPIVector> toor(thread, CreateVector());
368 uint32_t elementsNums = 20;
369 for (uint32_t i = 0; i < elementsNums; i++) {
370 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
371 JSAPIVector::Add(thread, toor, value);
372 }
373
374 // test RemoveByRange exception
375 // toIndex <= fromIndex
376 JSTaggedValue result1 = JSAPIVector::RemoveByRange(thread, toor, 0, 0);
377 EXPECT_EQ(result1, JSTaggedValue::Exception());
378 EXPECT_EXCEPTION();
379
380 // from < 0
381 JSTaggedValue result2 = JSAPIVector::RemoveByRange(thread, toor, -1, 0);
382 EXPECT_EQ(result2, JSTaggedValue::Exception());
383 EXPECT_EXCEPTION();
384
385 // fromIndex >= length
386 JSTaggedValue result3 = JSAPIVector::RemoveByRange(thread, toor, elementsNums, elementsNums * 2);
387 EXPECT_EQ(result3, JSTaggedValue::Exception());
388 EXPECT_EXCEPTION();
389 }
390
391 /**
392 * @tc.name: SubVector
393 * @tc.desc:
394 * @tc.type: FUNC
395 * @tc.require:
396 */
HWTEST_F_L0(JSAPIVectorTest,ExceptionOfSubVector)397 HWTEST_F_L0(JSAPIVectorTest, ExceptionOfSubVector)
398 {
399 JSHandle<JSAPIVector> toor(thread, CreateVector());
400 uint32_t elementsNums = 20;
401 for (uint32_t i = 0; i < elementsNums; i++) {
402 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
403 JSAPIVector::Add(thread, toor, value);
404 }
405
406 // test SubVector exception
407 // from < 0
408 JSAPIVector::SubVector(thread, toor, -1, 0);
409 EXPECT_EXCEPTION();
410
411 // toIndex < 0
412 JSAPIVector::SubVector(thread, toor, 0, -1);
413 EXPECT_EXCEPTION();
414
415 // fromIndex >= length
416 JSAPIVector::SubVector(thread, toor, elementsNums, 0);
417 EXPECT_EXCEPTION();
418
419 // ToIndex >= length
420 JSAPIVector::SubVector(thread, toor, 0, elementsNums);
421 EXPECT_EXCEPTION();
422
423 // toIndex <= fromIndex
424 JSAPIVector::SubVector(thread, toor, elementsNums - 1, 0);
425 EXPECT_EXCEPTION();
426 }
427
428 /**
429 * @tc.name: OwnKeys
430 * @tc.desc:
431 * @tc.type: FUNC
432 * @tc.require:
433 */
HWTEST_F_L0(JSAPIVectorTest,OwnKeys)434 HWTEST_F_L0(JSAPIVectorTest, OwnKeys)
435 {
436 JSHandle<JSAPIVector> toor(thread, CreateVector());
437 uint32_t elementsNums = 8;
438 for (uint32_t i = 0; i < elementsNums; i++) {
439 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
440 JSAPIVector::Add(thread, toor, value);
441 }
442 JSHandle<TaggedArray> keyArray = JSAPIVector::OwnKeys(thread, toor);
443 EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
444 EXPECT_TRUE(keyArray->GetLength() == elementsNums);
445 for (uint32_t i = 0; i < elementsNums; i++) {
446 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(
447 *(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
448 EcmaString::Cast(keyArray->Get(i).GetTaggedObject())
449 ));
450 }
451 }
452
453 /**
454 * @tc.name: GetFirstElement
455 * @tc.desc:
456 * @tc.type: FUNC
457 * @tc.require:
458 */
HWTEST_F_L0(JSAPIVectorTest,GetFirstElement)459 HWTEST_F_L0(JSAPIVectorTest, GetFirstElement)
460 {
461 JSHandle<JSAPIVector> toor(thread, CreateVector());
462 EXPECT_EQ(JSAPIVector::GetFirstElement(toor), JSTaggedValue::Undefined());
463
464 uint32_t elementsNums = 8;
465 for (uint32_t i = 0; i < elementsNums; i++) {
466 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
467 JSAPIVector::Add(thread, toor, value);
468 }
469 EXPECT_EQ(JSAPIVector::GetFirstElement(toor), JSTaggedValue(0));
470 }
471 } // namespace panda::test
472