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_linked_list.h"
21 #include "ecmascript/js_api/js_api_linked_list_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/tagged_list.h"
29 #include "ecmascript/tests/test_helper.h"
30
31 using namespace panda;
32
33 using namespace panda::ecmascript;
34
35 using namespace panda::ecmascript::containers;
36
37 namespace panda::test {
38 class JSAPILinkedListTest : public testing::Test {
39 public:
SetUpTestCase()40 static void SetUpTestCase()
41 {
42 GTEST_LOG_(INFO) << "SetUpTestCase";
43 }
44
TearDownTestCase()45 static void TearDownTestCase()
46 {
47 GTEST_LOG_(INFO) << "TearDownCase";
48 }
49
SetUp()50 void SetUp() override
51 {
52 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
53 }
54
TearDown()55 void TearDown() override
56 {
57 TestHelper::DestroyEcmaVMWithScope(instance, scope);
58 }
59
60 EcmaVM *instance {nullptr};
61 ecmascript::EcmaHandleScope *scope {nullptr};
62 JSThread *thread {nullptr};
63
64 protected:
CreateLinkedList()65 JSAPILinkedList *CreateLinkedList()
66 {
67 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
68 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
69
70 JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
71 JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
72 JSHandle<JSTaggedValue> value =
73 JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
74
75 auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
76 objCallInfo->SetFunction(JSTaggedValue::Undefined());
77 objCallInfo->SetThis(value.GetTaggedValue());
78 objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(containers::ContainerTag::LinkedList)));
79
80 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
81 JSHandle<JSTaggedValue> contianer =
82 JSHandle<JSTaggedValue>(thread, ContainersPrivate::Load(objCallInfo));
83 JSHandle<JSAPILinkedList> linkedList =
84 JSHandle<JSAPILinkedList>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(contianer),
85 contianer));
86 JSTaggedValue doubleList = TaggedDoubleList::Create(thread);
87 linkedList->SetDoubleList(thread, doubleList);
88 return *linkedList;
89 }
90 };
91
HWTEST_F_L0(JSAPILinkedListTest,LinkedListCreate)92 HWTEST_F_L0(JSAPILinkedListTest, LinkedListCreate)
93 {
94 JSAPILinkedList *linkedlist = CreateLinkedList();
95 EXPECT_TRUE(linkedlist != nullptr);
96 }
97
HWTEST_F_L0(JSAPILinkedListTest,AddAndHas)98 HWTEST_F_L0(JSAPILinkedListTest, AddAndHas)
99 {
100 constexpr int NODE_NUMBERS = 9;
101 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
102 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
103
104 JSHandle<JSAPILinkedList> toor(thread, CreateLinkedList());
105
106 std::string myValue("myvalue");
107 for (int i = 0; i < NODE_NUMBERS; i++) {
108 std::string ivalue = myValue + std::to_string(i);
109 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
110 JSAPILinkedList::Add(thread, toor, value);
111 }
112 EXPECT_EQ(toor->Length(), NODE_NUMBERS);
113
114 for (int i = 0; i < NODE_NUMBERS; i++) {
115 std::string ivalue = myValue + std::to_string(i);
116 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
117
118 JSTaggedValue gValue = toor->Get(i);
119 EXPECT_EQ(gValue, value.GetTaggedValue());
120 }
121 JSTaggedValue gValue = toor->Get(10);
122 EXPECT_EQ(gValue, JSTaggedValue::Undefined());
123
124 std::string ivalue = myValue + std::to_string(1);
125 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
126 EXPECT_TRUE(toor->Has(value.GetTaggedValue()));
127 }
128
HWTEST_F_L0(JSAPILinkedListTest,AddFirstAndGetFirst)129 HWTEST_F_L0(JSAPILinkedListTest, AddFirstAndGetFirst)
130 {
131 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
132 JSHandle<JSAPILinkedList> list(thread, CreateLinkedList());
133 list->Add(thread, list, value);
134 EXPECT_EQ(list->Length(), 1);
135 EXPECT_EQ(list->Get(0).GetInt(), 1);
136
137 JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(2));
138 list->AddFirst(thread, list, value1);
139 EXPECT_EQ(list->Length(), 2);
140 EXPECT_EQ(list->GetFirst().GetInt(), 2);
141 }
142
HWTEST_F_L0(JSAPILinkedListTest,InsertAndGetLast)143 HWTEST_F_L0(JSAPILinkedListTest, InsertAndGetLast)
144 { // create jsMap
145 constexpr uint32_t NODE_NUMBERS = 9;
146 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
147
148 JSHandle<JSAPILinkedList> toor(thread, CreateLinkedList());
149 EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
150 EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
151 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
152 value.Update(JSTaggedValue(i + 1));
153 JSAPILinkedList::Add(thread, toor, value);
154 }
155 EXPECT_EQ(toor->GetLast().GetInt(), 9);
156 EXPECT_EQ(toor->GetFirst().GetInt(), 1);
157
158 value.Update(JSTaggedValue(99));
159 int len = toor->Length();
160 toor->Insert(thread, toor, value, len);
161 EXPECT_EQ(toor->GetLast().GetInt(), 99);
162 EXPECT_EQ(toor->Length(), 10);
163
164 value.Update(JSTaggedValue(100));
165 toor->Insert(thread, toor, value, 0);
166 EXPECT_EQ(toor->GetFirst().GetInt(), 100);
167 EXPECT_EQ(toor->Length(), 11);
168
169 toor->Dump();
170
171 value.Update(JSTaggedValue(101));
172 toor->Insert(thread, toor, value, 5);
173 EXPECT_EQ(toor->Length(), 12);
174 toor->Dump();
175 EXPECT_EQ(toor->Get(5).GetInt(), 101);
176 }
177
HWTEST_F_L0(JSAPILinkedListTest,GetIndexOfAndGetLastIndexOf)178 HWTEST_F_L0(JSAPILinkedListTest, GetIndexOfAndGetLastIndexOf)
179 { // create jsMap
180 constexpr uint32_t NODE_NUMBERS = 9;
181 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
182
183 JSHandle<JSAPILinkedList> toor(thread, CreateLinkedList());
184 EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
185 EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
186 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
187 value.Update(JSTaggedValue(i + 1));
188 JSAPILinkedList::Add(thread, toor, value);
189 }
190 EXPECT_EQ(toor->GetLast().GetInt(), 9);
191 EXPECT_EQ(toor->GetFirst().GetInt(), 1);
192
193 value.Update(JSTaggedValue(99));
194 int len = toor->Length();
195 toor->Insert(thread, toor, value, len);
196 EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 9);
197 EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 9);
198 EXPECT_EQ(toor->Length(), 10);
199
200 value.Update(JSTaggedValue(100));
201 toor->Insert(thread, toor, value, 0);
202 EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 0);
203 EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 0);
204 EXPECT_EQ(toor->Length(), 11);
205
206 value.Update(JSTaggedValue(101));
207 toor->Insert(thread, toor, value, 5);
208 EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 5);
209 EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 5);
210 EXPECT_EQ(toor->Length(), 12);
211
212 toor->Dump();
213 }
214
HWTEST_F_L0(JSAPILinkedListTest,Remove)215 HWTEST_F_L0(JSAPILinkedListTest, Remove)
216 {
217 constexpr uint32_t NODE_NUMBERS = 20;
218 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
219
220 JSHandle<JSAPILinkedList> toor(thread, CreateLinkedList());
221 EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
222 EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
223 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
224 value.Update(JSTaggedValue(i));
225 JSAPILinkedList::Add(thread, toor, value);
226 }
227 EXPECT_EQ(toor->Length(), 20);
228 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
229 value.Update(JSTaggedValue(i));
230 JSTaggedValue gValue = toor->Get(i);
231 EXPECT_EQ(gValue, value.GetTaggedValue());
232 }
233
234 EXPECT_EQ(JSAPILinkedList::RemoveFirst(thread, toor), JSTaggedValue(0));
235 value.Update(JSTaggedValue(0));
236 EXPECT_EQ(toor->Has(value.GetTaggedValue()), false);
237 EXPECT_EQ(toor->Length(), 19);
238
239 EXPECT_EQ(JSAPILinkedList::RemoveLast(thread, toor), JSTaggedValue(19));
240 value.Update(JSTaggedValue(19));
241 EXPECT_EQ(toor->Has(value.GetTaggedValue()), false);
242 EXPECT_EQ(toor->Length(), 18);
243
244 value.Update(JSTaggedValue(5));
245 EXPECT_EQ(JSAPILinkedList::RemoveByIndex(thread, toor, 4), value.GetTaggedValue());
246 EXPECT_EQ(toor->Has(value.GetTaggedValue()), false);
247 EXPECT_EQ(toor->Length(), 17);
248
249 value.Update(JSTaggedValue(8));
250 EXPECT_EQ(toor->Remove(thread, value.GetTaggedValue()), JSTaggedValue::True());
251 EXPECT_EQ(toor->Has(value.GetTaggedValue()), false);
252 EXPECT_EQ(toor->Length(), 16);
253
254 value.Update(JSTaggedValue(11));
255 EXPECT_EQ(JSAPILinkedList::RemoveFirstFound(thread, toor, value.GetTaggedValue()), JSTaggedValue::True());
256 EXPECT_EQ(toor->Has(value.GetTaggedValue()), false);
257 EXPECT_EQ(toor->Length(), 15);
258
259 value.Update(JSTaggedValue(14));
260 EXPECT_EQ(JSAPILinkedList::RemoveLastFound(thread, toor, value.GetTaggedValue()), JSTaggedValue::True());
261 EXPECT_EQ(toor->Has(value.GetTaggedValue()), false);
262 EXPECT_EQ(toor->Length(), 14);
263
264 toor->Dump();
265 }
266
HWTEST_F_L0(JSAPILinkedListTest,SpecialReturnOfRemove)267 HWTEST_F_L0(JSAPILinkedListTest, SpecialReturnOfRemove)
268 {
269 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
270 JSHandle<JSAPILinkedList> linkedList(thread, CreateLinkedList());
271 JSAPILinkedList::RemoveFirst(thread, linkedList);
272 EXPECT_EXCEPTION();
273
274 JSAPILinkedList::RemoveLast(thread, linkedList);
275 EXPECT_EXCEPTION();
276
277 JSAPILinkedList::RemoveFirstFound(thread, linkedList, value.GetTaggedValue());
278 EXPECT_EXCEPTION();
279
280 // test Remove and RemoveLastFound linkedlist whose nodeLength less than 0
281 JSHandle<TaggedDoubleList> doubleList(thread, linkedList->GetDoubleList());
282 doubleList->SetNumberOfNodes(thread, -1);
283 EXPECT_EQ(linkedList->Remove(thread, value.GetTaggedValue()), JSTaggedValue::False());
284
285 JSAPILinkedList::RemoveFirstFound(thread, linkedList, value.GetTaggedValue());
286 EXPECT_EXCEPTION();
287 }
288
HWTEST_F_L0(JSAPILinkedListTest,Clear)289 HWTEST_F_L0(JSAPILinkedListTest, Clear)
290 {
291 JSAPILinkedList *linkedlist = CreateLinkedList();
292
293 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
294 JSHandle<JSAPILinkedList> list(thread, linkedlist);
295 JSAPILinkedList::Add(thread, list, value);
296
297 JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(2));
298 JSAPILinkedList::Insert(thread, list, value1, 0);
299
300 list->Clear(thread);
301
302 EXPECT_EQ(list->Length(), 0);
303 EXPECT_TRUE(list->GetFirst().IsUndefined());
304 }
305
HWTEST_F_L0(JSAPILinkedListTest,Set)306 HWTEST_F_L0(JSAPILinkedListTest, Set)
307 {
308 constexpr uint32_t NODE_NUMBERS = 20;
309 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
310
311 JSHandle<JSAPILinkedList> toor(thread, CreateLinkedList());
312 EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
313 EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
314 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
315 value.Update(JSTaggedValue(i));
316 JSAPILinkedList::Add(thread, toor, value);
317 }
318 EXPECT_EQ(toor->Length(), 20);
319
320 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
321 value.Update(JSTaggedValue(i));
322 JSTaggedValue gValue = toor->Get(i);
323 EXPECT_EQ(gValue, value.GetTaggedValue());
324 }
325
326 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
327 value.Update(JSTaggedValue(i + 1));
328 JSAPILinkedList::Set(thread, toor, i, value);
329 }
330
331 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
332 value.Update(JSTaggedValue(i + 1));
333 JSTaggedValue gValue = toor->Get(i);
334 EXPECT_EQ(gValue, value.GetTaggedValue());
335 }
336 }
337
HWTEST_F_L0(JSAPILinkedListTest,GetOwnProperty)338 HWTEST_F_L0(JSAPILinkedListTest, GetOwnProperty)
339 {
340 constexpr uint32_t DEFAULT_LENGTH = 8;
341 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
342 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
343 JSHandle<JSAPILinkedList> toor(thread, CreateLinkedList());
344
345 std::string linkedListvalue("linkedListvalue");
346 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
347 std::string ivalue = linkedListvalue + std::to_string(i);
348 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
349 JSAPILinkedList::Add(thread, toor, value);
350 }
351 // test GetOwnProperty
352 int testInt = 1;
353 JSHandle<JSTaggedValue> linkedListKey1(thread, JSTaggedValue(testInt));
354 EXPECT_TRUE(JSAPILinkedList::GetOwnProperty(thread, toor, linkedListKey1));
355 testInt = 20;
356 JSHandle<JSTaggedValue> linkedListKey2(thread, JSTaggedValue(testInt));
357 EXPECT_FALSE(JSAPILinkedList::GetOwnProperty(thread, toor, linkedListKey2));
358 EXPECT_EXCEPTION();
359
360 // test GetOwnProperty exception
361 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
362 EXPECT_FALSE(JSAPILinkedList::GetOwnProperty(thread, toor, undefined));
363 EXPECT_EXCEPTION();
364 }
365
366 /**
367 * @tc.name: GetProperty
368 * @tc.desc:
369 * @tc.type: FUNC
370 * @tc.require:
371 */
HWTEST_F_L0(JSAPILinkedListTest,GetProperty)372 HWTEST_F_L0(JSAPILinkedListTest, GetProperty)
373 {
374 JSHandle<JSAPILinkedList> toor(thread, CreateLinkedList());
375 uint32_t elementsNums = 8;
376 for (uint32_t i = 0; i < elementsNums; i++) {
377 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
378 JSAPILinkedList::Add(thread, toor, value);
379 }
380 for (uint32_t i = 0; i < elementsNums; i++) {
381 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
382 OperationResult getPropertyRes = JSAPILinkedList::GetProperty(thread, toor, key);
383 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
384 }
385 }
386
387 /**
388 * @tc.name: SetProperty
389 * @tc.desc:
390 * @tc.type: FUNC
391 * @tc.require:
392 */
HWTEST_F_L0(JSAPILinkedListTest,SetProperty)393 HWTEST_F_L0(JSAPILinkedListTest, SetProperty)
394 {
395 JSHandle<JSAPILinkedList> toor(thread, CreateLinkedList());
396 uint32_t elementsNums = 8;
397 for (uint32_t i = 0; i < elementsNums; i++) {
398 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
399 JSAPILinkedList::Add(thread, toor, value);
400 }
401 for (uint32_t i = 0; i < elementsNums; i++) {
402 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
403 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
404 bool setPropertyRes = JSAPILinkedList::SetProperty(thread, toor, key, value);
405 EXPECT_EQ(setPropertyRes, true);
406 }
407 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
408 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
409 EXPECT_FALSE(JSAPILinkedList::SetProperty(thread, toor, key, value));
410 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
411 EXPECT_FALSE(JSAPILinkedList::SetProperty(thread, toor, key1, value));
412 }
413
HWTEST_F_L0(JSAPILinkedListTest,Clone)414 HWTEST_F_L0(JSAPILinkedListTest, Clone)
415 {
416 uint32_t elementsNums = 8;
417 JSAPILinkedList *linkedlist = CreateLinkedList();
418 JSHandle<JSAPILinkedList> list(thread, linkedlist);
419 for (uint32_t i = 0; i < elementsNums; i++) {
420 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
421 JSAPILinkedList::Add(thread, list, value);
422 }
423 JSHandle<JSAPILinkedList> cloneList = JSAPILinkedList::Clone(thread, list);
424
425 for (uint32_t i = 0; i < elementsNums; i++) {
426 EXPECT_EQ(cloneList->Get(i), list->Get(i));
427 }
428 EXPECT_EQ(list->Length(), cloneList->Length());
429 }
430
HWTEST_F_L0(JSAPILinkedListTest,OwnKeys)431 HWTEST_F_L0(JSAPILinkedListTest, OwnKeys)
432 {
433 uint32_t elementsNums = 8;
434 JSHandle<JSAPILinkedList> linkedList(thread, CreateLinkedList());
435 for (uint32_t i = 0; i < elementsNums; i++) {
436 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
437 JSAPILinkedList::Add(thread, linkedList, value);
438 }
439 JSHandle<TaggedArray> keyArray = JSAPILinkedList::OwnKeys(thread, linkedList);
440 EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
441 EXPECT_TRUE(keyArray->GetLength() == elementsNums);
442 for (uint32_t i = 0; i < elementsNums; i++) {
443 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
444 EcmaString::Cast(keyArray->Get(i).GetTaggedObject())));
445 }
446 }
447 } // namespace panda::test
448