• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_list.h"
21 #include "ecmascript/js_api/js_api_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 JSAPIListTest : 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:
CreateList()65     JSAPIList *CreateList()
66     {
67         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
68         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
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::List)));
79 
80         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
81         JSTaggedValue result = containers::ContainersPrivate::Load(objCallInfo);
82         TestHelper::TearDownFrame(thread, prev);
83 
84         JSHandle<JSTaggedValue> constructor(thread, result);
85         JSHandle<JSAPIList> list(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
86         JSTaggedValue singleList = TaggedSingleList::Create(thread);
87         list->SetSingleList(thread, singleList);
88         return *list;
89     }
90 };
91 
HWTEST_F_L0(JSAPIListTest,listCreate)92 HWTEST_F_L0(JSAPIListTest, listCreate)
93 {
94     JSAPIList *list = CreateList();
95     EXPECT_TRUE(list != nullptr);
96 }
97 
HWTEST_F_L0(JSAPIListTest,AddHasAndIsEmpty)98 HWTEST_F_L0(JSAPIListTest, AddHasAndIsEmpty)
99 {
100     constexpr int NODE_NUMBERS = 9;
101     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
102     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
103 
104     JSHandle<JSAPIList> toor(thread, CreateList());
105 
106     EXPECT_TRUE(toor->IsEmpty());
107 
108     std::string myValue("myvalue");
109     for (int i = 0; i < NODE_NUMBERS; i++) {
110         std::string ivalue = myValue + std::to_string(i);
111         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
112         JSAPIList::Add(thread, toor, value);
113     }
114     EXPECT_EQ(toor->Length(), NODE_NUMBERS);
115     EXPECT_FALSE(toor->IsEmpty());
116 
117     for (int i = 0; i < NODE_NUMBERS; i++) {
118         std::string ivalue = myValue + std::to_string(i);
119         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
120 
121         JSTaggedValue gValue = toor->Get(i);
122         EXPECT_EQ(gValue, value.GetTaggedValue());
123     }
124     JSTaggedValue gValue = toor->Get(10);
125     EXPECT_EQ(gValue, JSTaggedValue::Undefined());
126 
127     std::string ivalue = myValue + std::to_string(1);
128     value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
129     EXPECT_TRUE(toor->Has(value.GetTaggedValue()));
130 
131     toor->Dump();
132 }
133 
HWTEST_F_L0(JSAPIListTest,InsertAndGetLastAndGetFirst)134 HWTEST_F_L0(JSAPIListTest, InsertAndGetLastAndGetFirst)
135 {    // create jsMap
136     constexpr uint32_t NODE_NUMBERS = 9;
137     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
138 
139     JSHandle<JSAPIList> toor(thread, CreateList());
140     EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
141     EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
142     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
143         value.Update(JSTaggedValue(i + 1));
144         JSAPIList::Add(thread, toor, value);
145     }
146     EXPECT_EQ(toor->GetLast().GetInt(), 9);
147     EXPECT_EQ(toor->GetFirst().GetInt(), 1);
148 
149     value.Update(JSTaggedValue(99));
150     int len = toor->Length();
151     toor->Insert(thread, toor, value, len);
152     EXPECT_EQ(toor->GetLast().GetInt(), 99);
153     EXPECT_EQ(toor->Length(), 10);
154 
155     value.Update(JSTaggedValue(100));
156     toor->Insert(thread, toor, value, 0);
157     EXPECT_EQ(toor->GetFirst().GetInt(), 100);
158     EXPECT_EQ(toor->Length(), 11);
159 
160     toor->Dump();
161 
162     value.Update(JSTaggedValue(101));
163     toor->Insert(thread, toor, value, 5);
164     EXPECT_EQ(toor->Length(), 12);
165     toor->Dump();
166     EXPECT_EQ(toor->Get(5).GetInt(), 101);
167 }
168 
HWTEST_F_L0(JSAPIListTest,GetIndexOfAndGetLastIndexOf)169 HWTEST_F_L0(JSAPIListTest, GetIndexOfAndGetLastIndexOf)
170 {    // create jsMap
171     constexpr uint32_t NODE_NUMBERS = 9;
172     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
173 
174     JSHandle<JSAPIList> toor(thread, CreateList());
175     EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
176     EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
177     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
178         value.Update(JSTaggedValue(i + 1));
179         JSAPIList::Add(thread, toor, value);
180     }
181     EXPECT_EQ(toor->GetLast().GetInt(), 9);
182     EXPECT_EQ(toor->GetFirst().GetInt(), 1);
183 
184     value.Update(JSTaggedValue(99));
185     int len = toor->Length();
186     toor->Insert(thread, toor, value, len);
187     EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 9);
188     EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 9);
189     EXPECT_EQ(toor->Length(), 10);
190 
191     value.Update(JSTaggedValue(100));
192     toor->Insert(thread, toor, value, 0);
193     EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 0);
194     EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 0);
195     EXPECT_EQ(toor->Length(), 11);
196 
197     value.Update(JSTaggedValue(101));
198     toor->Insert(thread, toor, value, 5);
199     EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 5);
200     EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 5);
201     EXPECT_EQ(toor->Length(), 12);
202 
203     toor->Dump();
204 }
205 
HWTEST_F_L0(JSAPIListTest,Remove)206 HWTEST_F_L0(JSAPIListTest, Remove)
207 {    // create jsMap
208     constexpr uint32_t NODE_NUMBERS = 20;
209     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
210 
211     JSHandle<JSAPIList> toor(thread, CreateList());
212     EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
213     EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
214     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
215         value.Update(JSTaggedValue(i));
216         JSAPIList::Add(thread, toor, value);
217     }
218     EXPECT_EQ(toor->Length(), 20);
219     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
220         value.Update(JSTaggedValue(i));
221         JSTaggedValue gValue = toor->Get(i);
222         EXPECT_EQ(gValue, value.GetTaggedValue());
223     }
224 
225     value.Update(JSTaggedValue(4));
226     EXPECT_EQ(JSAPIList::RemoveByIndex(thread, toor, 4), value.GetTaggedValue());
227     EXPECT_EQ(toor->Has(value.GetTaggedValue()), false);
228     EXPECT_EQ(toor->Length(), 19);
229 
230     value.Update(JSTaggedValue(8));
231     EXPECT_EQ(toor->Remove(thread, value.GetTaggedValue()), JSTaggedValue::True());
232     EXPECT_EQ(toor->Has(value.GetTaggedValue()), false);
233     EXPECT_EQ(toor->Length(), 18);
234 
235     toor->Dump();
236 }
237 
HWTEST_F_L0(JSAPIListTest,Clear)238 HWTEST_F_L0(JSAPIListTest, Clear)
239 {
240     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
241     JSHandle<JSAPIList> list(thread, CreateList());
242     JSAPIList::Add(thread, list, value);
243 
244     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(2));
245     JSAPIList::Insert(thread, list, value1, 0);
246 
247     list->Clear(thread);
248 
249     EXPECT_EQ(list->Length(), 0);
250     EXPECT_TRUE(list->GetFirst().IsUndefined());
251 }
252 
HWTEST_F_L0(JSAPIListTest,Set)253 HWTEST_F_L0(JSAPIListTest, Set)
254 {
255     constexpr uint32_t NODE_NUMBERS = 20;
256     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
257 
258     JSHandle<JSAPIList> toor(thread, CreateList());
259     EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
260     EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
261     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
262         value.Update(JSTaggedValue(i));
263         JSAPIList::Add(thread, toor, value);
264     }
265     EXPECT_EQ(toor->Length(), 20);
266 
267     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
268         value.Update(JSTaggedValue(i));
269         JSTaggedValue gValue = toor->Get(i);
270         EXPECT_EQ(gValue, value.GetTaggedValue());
271     }
272 
273     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
274         value.Update(JSTaggedValue(i + 1));
275         JSAPIList::Set(thread, toor, i, value);
276     }
277 
278     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
279         value.Update(JSTaggedValue(i + 1));
280         JSTaggedValue gValue = toor->Get(i);
281         EXPECT_EQ(gValue, value.GetTaggedValue());
282     }
283 }
284 
HWTEST_F_L0(JSAPIListTest,GetOwnProperty)285 HWTEST_F_L0(JSAPIListTest, GetOwnProperty)
286 {
287     constexpr uint32_t DEFAULT_LENGTH = 8;
288     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
289     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
290     JSHandle<JSAPIList> toor(thread, CreateList());
291 
292     std::string listvalue("listvalue");
293     for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
294         std::string ivalue = listvalue + std::to_string(i);
295         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
296         JSAPIList::Add(thread, toor, value);
297     }
298     // test GetOwnProperty
299     int testInt = 1;
300     JSHandle<JSTaggedValue> listKey1(thread, JSTaggedValue(testInt));
301     EXPECT_TRUE(JSAPIList::GetOwnProperty(thread, toor, listKey1));
302     testInt = 20;
303     JSHandle<JSTaggedValue> listKey2(thread, JSTaggedValue(testInt));
304     EXPECT_FALSE(JSAPIList::GetOwnProperty(thread, toor, listKey2));
305     EXPECT_EXCEPTION();
306 
307     // test GetOwnProperty exception
308     JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
309     EXPECT_FALSE(JSAPIList::GetOwnProperty(thread, toor, undefined));
310     EXPECT_EXCEPTION();
311 }
312 
313 /**
314  * @tc.name: GetProperty
315  * @tc.desc:
316  * @tc.type: FUNC
317  * @tc.require:
318  */
HWTEST_F_L0(JSAPIListTest,GetProperty)319 HWTEST_F_L0(JSAPIListTest, GetProperty)
320 {
321     JSHandle<JSAPIList> toor(thread, CreateList());
322     uint32_t elementsNums = 8;
323     for (uint32_t i = 0; i < elementsNums; i++) {
324         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
325         JSAPIList::Add(thread, toor, value);
326     }
327     for (uint32_t i = 0; i < elementsNums; i++) {
328         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
329         OperationResult getPropertyRes = JSAPIList::GetProperty(thread, toor, key);
330         EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
331     }
332 }
333 
334 /**
335  * @tc.name: SetProperty
336  * @tc.desc:
337  * @tc.type: FUNC
338  * @tc.require:
339  */
HWTEST_F_L0(JSAPIListTest,SetProperty)340 HWTEST_F_L0(JSAPIListTest, SetProperty)
341 {
342     JSHandle<JSAPIList> toor(thread, CreateList());
343     uint32_t elementsNums = 8;
344     for (uint32_t i = 0; i < elementsNums; i++) {
345         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
346         JSAPIList::Add(thread, toor, value);
347     }
348     for (uint32_t i = 0; i < elementsNums; i++) {
349         JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
350         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
351         bool setPropertyRes = JSAPIList::SetProperty(thread, toor, key, value);
352         EXPECT_EQ(setPropertyRes, true);
353     }
354     JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
355     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
356     EXPECT_FALSE(JSAPIList::SetProperty(thread, toor, key, value));
357     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
358     EXPECT_FALSE(JSAPIList::SetProperty(thread, toor, key1, value));
359 }
360 
361 /**
362  * @tc.name: GetSubList
363  * @tc.desc:
364  * @tc.type: FUNC
365  * @tc.require:
366  */
HWTEST_F_L0(JSAPIListTest,GetSubList)367 HWTEST_F_L0(JSAPIListTest, GetSubList)
368 {
369     JSHandle<JSAPIList> List(thread, CreateList());
370     uint32_t addElementNums = 256;
371     for (uint32_t i = 0; i < addElementNums; i++) {
372         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
373         JSAPIList::Add(thread, List, value);
374     }
375 
376     // throw error test
377     uint32_t smallIndex = -1;
378     uint32_t bigIndex = List->Length() + 10;
379     uint32_t zeroIndex = 0;
380 
381     // fromIndex < 0
382     JSAPIList::GetSubList(thread, List, smallIndex, zeroIndex);
383     EXPECT_EXCEPTION();
384 
385     // fromIndex >= size
386     JSAPIList::GetSubList(thread, List, bigIndex, zeroIndex);
387     EXPECT_EXCEPTION();
388 
389     // toIndex <= fromIndex
390     JSAPIList::GetSubList(thread, List, zeroIndex, zeroIndex);
391     EXPECT_EXCEPTION();
392 
393     // toIndex < 0
394     JSAPIList::GetSubList(thread, List, zeroIndex, smallIndex);
395     EXPECT_EXCEPTION();
396 
397     // toIndex > length
398     JSAPIList::GetSubList(thread, List, zeroIndex, bigIndex);
399     EXPECT_EXCEPTION();
400 }
401 
HWTEST_F_L0(JSAPIListTest,OwnKeys)402 HWTEST_F_L0(JSAPIListTest, OwnKeys)
403 {
404     uint32_t elementsNums = 8;
405     JSHandle<JSAPIList> list(thread, CreateList());
406     for (uint32_t i = 0; i < elementsNums; i++) {
407         JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
408         JSAPIList::Add(thread, list, value);
409     }
410     JSHandle<TaggedArray> keyArray = JSAPIList::OwnKeys(thread, list);
411     EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
412     EXPECT_TRUE(keyArray->GetLength() == elementsNums);
413     for (uint32_t i = 0; i < elementsNums; i++) {
414         ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
415             EcmaString::Cast(keyArray->Get(i).GetTaggedObject())));
416     }
417 }
418 }  // namespace panda::test
419