• 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/js_stable_array.h"
17 #include "ecmascript/tests/test_helper.h"
18 
19 using namespace panda;
20 using namespace panda::ecmascript;
21 
22 namespace panda::test {
23 class JSStableArrayTest : public testing::Test {
24 public:
SetUpTestCase()25     static void SetUpTestCase()
26     {
27         GTEST_LOG_(INFO) << "SetUpTestCase";
28     }
29 
TearDownTestCase()30     static void TearDownTestCase()
31     {
32         GTEST_LOG_(INFO) << "TearDownCase";
33     }
34 
SetUp()35     void SetUp() override
36     {
37         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
38     }
39 
TearDown()40     void TearDown() override
41     {
42         TestHelper::DestroyEcmaVMWithScope(instance, scope);
43     }
44 
45     EcmaVM *instance {nullptr};
46     EcmaHandleScope *scope {nullptr};
47     JSThread *thread {nullptr};
48 };
49 
50 /**
51  * @tc.name: Push
52  * @tc.desc: Change a JSArray through calling Push function with the JSArray and a EcmaRuntimeCallInfo, check whether
53  *           the TaggedArray of the JSArray is within expectations.
54  * @tc.type: FUNC
55  * @tc.require:
56  */
HWTEST_F_L0(JSStableArrayTest,Push)57 HWTEST_F_L0(JSStableArrayTest, Push)
58 {
59     int32_t lengthArr = 99;
60     int32_t numElementsPush = 9;
61     JSHandle<JSTaggedValue> handleTagValArr = JSArray::ArrayCreate(thread, JSTaggedNumber(lengthArr));
62     JSHandle<JSArray> handleArr(handleTagValArr);
63 
64     auto ecmaRuntimeCallInfo =
65         TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4 + 2 * numElementsPush);
66     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
67     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
68     for (int32_t i = 0; i < numElementsPush; i++) {
69         ecmaRuntimeCallInfo->SetCallArg(i, JSTaggedValue(i));
70     }
71     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
72     EXPECT_EQ(JSStableArray::Push(handleArr, ecmaRuntimeCallInfo),
73               JSTaggedValue(lengthArr + numElementsPush));
74     TestHelper::TearDownFrame(thread, prev);
75 
76     JSHandle<TaggedArray> handleTagArr(thread, TaggedArray::Cast(handleArr->GetElements().GetTaggedObject()));
77     EXPECT_EQ(handleArr->GetArrayLength(), static_cast<size_t>(lengthArr + numElementsPush));
78     for (int32_t i = lengthArr; i < lengthArr + numElementsPush; i++) {
79         EXPECT_EQ(handleTagArr->Get(i).GetNumber(), i - lengthArr);
80     }
81 }
82 
83 /**
84  * @tc.name: Pop
85  * @tc.desc: Change a JSArray through calling Pop function with the JSArray and a EcmaRuntimeCallInfo, check whether
86  *           the JSArray and the TaggedArray of the JSArray are within expectations.
87  * @tc.type: FUNC
88  * @tc.require:
89  */
HWTEST_F_L0(JSStableArrayTest,Pop)90 HWTEST_F_L0(JSStableArrayTest, Pop)
91 {
92     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
93 
94     int32_t lengthArr = 49;
95     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
96     for (int i = 0; i < lengthArr; i++) {
97         handleTagArr->Set(thread, i, JSTaggedValue(i));
98     }
99     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
100 
101     for (int32_t i = 1; i < 6; i++) {
102         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
103         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
104         ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
105         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
106         EXPECT_EQ(JSStableArray::Pop(handleArr, ecmaRuntimeCallInfo), JSTaggedValue(lengthArr - i));
107         TestHelper::TearDownFrame(thread, prev);
108 
109         EXPECT_EQ(handleArr->GetArrayLength(), static_cast<uint32_t>(lengthArr - i));
110         if (i != 5) {
111             EXPECT_EQ(handleTagArr->GetLength(), static_cast<uint32_t>(lengthArr));
112             EXPECT_EQ(handleTagArr->Get(lengthArr - i), JSTaggedValue::Hole());
113         } else {
114             EXPECT_EQ(handleTagArr->GetLength(), static_cast<uint32_t>(lengthArr - i));
115         }
116     }
117 }
118 
119 /**
120  * @tc.name: Splice
121  * @tc.desc: Create a source TaggedArray, set value for the elements of the source TaggedArray, create an source Array
122  *           through calling CreateArrayFromList function with the source TaggedArray, create a deleted Array through
123  *           calling Splice function with the source Array, an EcmaRuntimeCallInfo that set Args from 2 as the
124  *           delete-elements, the offsetStartInsert, the countInsert and the actualDeleteCount. Check whether the
125  *           deleted Array and the source Array after change are within expectations.
126  * @tc.type: FUNC
127  * @tc.require:
128  */
HWTEST_F_L0(JSStableArrayTest,Splice)129 HWTEST_F_L0(JSStableArrayTest, Splice)
130 {
131     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
132 
133     int32_t lengthArr = 49;
134 
135     JSHandle<JSTaggedValue> handleTagValInsertElement1(thread, JSTaggedValue(4000));
136     JSHandle<JSTaggedValue> handleTagValInsertElement2(thread, JSTaggedValue(4100));
137     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
138     for (int i = 0; i < lengthArr; i++) {
139         handleTagArr->Set(thread, i, JSTaggedValue(i * 10));
140     }
141     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
142     double offsetStartInsert = 40;
143     double actualDeleteCount = 3;
144     double countInsert = 2;
145 
146     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(),
147         4 + (2 + countInsert) * 2);
148     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
149     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
150     ecmaRuntimeCallInfo->SetCallArg(2, handleTagValInsertElement1.GetTaggedValue());
151     ecmaRuntimeCallInfo->SetCallArg(3, handleTagValInsertElement2.GetTaggedValue());
152 
153     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
154     JSHandle<JSTaggedValue> handleTagValArrCombinedOfDeletedElements(thread,
155         JSStableArray::Splice(handleArr, ecmaRuntimeCallInfo, offsetStartInsert, countInsert,
156             actualDeleteCount));
157     TestHelper::TearDownFrame(thread, prev);
158     JSHandle<JSArray> handleArrCombinedOfDeletedElements(handleTagValArrCombinedOfDeletedElements);
159     EXPECT_EQ(handleArrCombinedOfDeletedElements->GetArrayLength(), actualDeleteCount);
160     JSHandle<JSObject> handleObjArrCombinedOfDeletedElements(handleTagValArrCombinedOfDeletedElements);
161     JSHandle<JSTaggedValue> handleTagValTagArrCombinedOfDeletedElements(thread,
162         handleObjArrCombinedOfDeletedElements->GetElements());
163     JSHandle<TaggedArray> handleTagArrCombinedOfDeletedElements(handleTagValTagArrCombinedOfDeletedElements);
164     for (int32_t i = 0; i < actualDeleteCount; i++) {
165         EXPECT_EQ(handleTagArrCombinedOfDeletedElements->Get(i).GetNumber(), (offsetStartInsert + i) * 10);
166     }
167 
168     // Check the JSArray(in-out-parameter) changed through calling the Splice function.
169     EXPECT_EQ(handleArr->GetArrayLength(), lengthArr - actualDeleteCount + countInsert);
170     for (int32_t i = 0; i < offsetStartInsert; i++) {
171         EXPECT_EQ(handleTagArr->Get(i).GetNumber(), i * 10);
172     }
173     EXPECT_EQ(handleTagArr->Get(offsetStartInsert).GetNumber(),
174               handleTagValInsertElement1.GetTaggedValue().GetNumber());
175     EXPECT_EQ(handleTagArr->Get(offsetStartInsert + 1).GetNumber(),
176               handleTagValInsertElement2.GetTaggedValue().GetNumber());
177     for (int32_t i = offsetStartInsert + countInsert; i < lengthArr - actualDeleteCount + countInsert; i++) {
178         EXPECT_EQ(handleTagArr->Get(i).GetNumber(), (i + actualDeleteCount - countInsert) * 10);
179     }
180 }
181 
182 /**
183  * @tc.name: Shift
184  * @tc.desc: Create a source Array, set value for the elements of the source Array, call the Shift function with the
185  *           source Array 5 times, check whether the returned JSTaggedValue and the changed source Array are within
186  *           expectations after each call to the Shift function.
187  * @tc.type: FUNC
188  * @tc.require:
189  */
HWTEST_F_L0(JSStableArrayTest,Shift)190 HWTEST_F_L0(JSStableArrayTest, Shift)
191 {
192     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
193 
194     int32_t lengthArr = 49;
195     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
196     for (int i = 0; i < lengthArr; i++) {
197         handleTagArr->Set(thread, i, JSTaggedValue(i * 10));
198     }
199     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
200 
201     for (int32_t i = 0; i < 5; i++) {
202         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
203         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
204         ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
205         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
206         EXPECT_EQ(JSStableArray::Shift(handleArr, ecmaRuntimeCallInfo), JSTaggedValue(i * 10));
207         TestHelper::TearDownFrame(thread, prev);
208         EXPECT_EQ(handleArr->GetArrayLength(), static_cast<uint32_t>(lengthArr - (i + 1)));
209         EXPECT_EQ(handleTagArr->Get(0), JSTaggedValue((i + 1) * 10));
210         if (i != 4) {
211             EXPECT_EQ(handleTagArr->GetLength(), static_cast<uint32_t>(lengthArr));
212             EXPECT_EQ(handleTagArr->Get(lengthArr - (i + 1)), JSTaggedValue::Hole());
213             continue;
214         }
215         EXPECT_EQ(handleTagArr->GetLength(), static_cast<uint32_t>(lengthArr - (i + 1)));
216     }
217 }
218 
219 /**
220  * @tc.name: Join_NumberElements_UndefinedSep
221  * @tc.desc: Create a source Array whose elements are Numbers and an EcmaRuntimeCallInfo, check whether the EcmaString
222  *           returned through calling Join function with the source Array and the EcmaRuntimeCallInfo is within
223  *           expectations.
224  * @tc.type: FUNC
225  * @tc.require:
226  */
HWTEST_F_L0(JSStableArrayTest,Join_NumberElements_UndefinedSep)227 HWTEST_F_L0(JSStableArrayTest, Join_NumberElements_UndefinedSep)
228 {
229     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
230 
231     int32_t lengthArr = 10;
232     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
233     for (int i = 0; i < lengthArr; i++) {
234         handleTagArr->Set(thread, i, JSTaggedValue(i));
235     }
236     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
237     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
238     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
239     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
240     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
241     JSHandle<JSTaggedValue> handleTagValEcmaStrRet(thread,
242         JSStableArray::Join(handleArr, ecmaRuntimeCallInfo));
243     TestHelper::TearDownFrame(thread, prev);
244 
245     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
246     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), "0,1,2,3,4,5,6,7,8,9");
247 }
248 
249 /**
250  * @tc.name: Join_StringElements_UndefinedSep
251  * @tc.desc: Create a source Array whose elements are EcmaStrings and an EcmaRuntimeCallInfo, check whether the
252  *           EcmaString returned through calling Join function with the source Array and the EcmaRuntimeCallInfo is
253  *           within expectations.
254  * @tc.type: FUNC
255  * @tc.require:
256  */
HWTEST_F_L0(JSStableArrayTest,Join_StringElements_UndefinedSep)257 HWTEST_F_L0(JSStableArrayTest, Join_StringElements_UndefinedSep)
258 {
259     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
260 
261     int32_t lengthArr = 10;
262     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
263     JSHandle<JSTaggedValue> handleTagValElementEcmaStr(objFactory->NewFromStdString("abc"));
264     for (int i = 0; i < lengthArr; i++) {
265         handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue());
266     }
267     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
268     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
269     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
270     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
271     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
272     JSHandle<JSTaggedValue> handleTagValEcmaStrRet(thread,
273         JSStableArray::Join(handleArr, ecmaRuntimeCallInfo));
274     TestHelper::TearDownFrame(thread, prev);
275 
276     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
277     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), "abc,abc,abc,abc,abc,abc,abc,abc,abc,abc");
278 }
279 
280 /**
281  * @tc.name: Join_NumberElements_DefinedSep
282  * @tc.desc: Create a source Array whose elements are Numbers and an EcmaRuntimeCallInfo, define the first arg of the
283              EcmaRuntimeCallInfo an EcmaString as the seperator, check whether the EcmaString returned through calling
284              Join function with the source Array and the EcmaRuntimeCallInfo is within expectations.
285  * @tc.type: FUNC
286  * @tc.require:
287  */
HWTEST_F_L0(JSStableArrayTest,Join_NumberElements_DefinedSep)288 HWTEST_F_L0(JSStableArrayTest, Join_NumberElements_DefinedSep)
289 {
290     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
291 
292     int32_t lengthArr = 10;
293     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
294     for (int i = 0; i < lengthArr; i++) {
295         handleTagArr->Set(thread, i, JSTaggedValue(i));
296     }
297     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
298     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
299     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
300     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
301     ecmaRuntimeCallInfo->SetCallArg(0,
302         JSHandle<JSTaggedValue>::Cast(objFactory->NewFromStdString("^")).GetTaggedValue());
303     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
304     JSHandle<JSTaggedValue> handleTagValEcmaStrRet(thread,
305         JSStableArray::Join(handleArr, ecmaRuntimeCallInfo));
306     TestHelper::TearDownFrame(thread, prev);
307 
308     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
309     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), "0^1^2^3^4^5^6^7^8^9");
310 }
311 
312 /**
313  * @tc.name: Join_StringElements_DefinedSep
314  * @tc.desc: Create a source Array whose elements are EcmaStrings and an EcmaRuntimeCallInfo, define the first arg of
315              the EcmaRuntimeCallInfo an EcmaString as the seperator, check whether the EcmaString returned through
316              calling Join function with the source Array and the EcmaRuntimeCallInfo is within expectations.
317  * @tc.type: FUNC
318  * @tc.require:
319  */
HWTEST_F_L0(JSStableArrayTest,Join_StringElements_DefinedSep)320 HWTEST_F_L0(JSStableArrayTest, Join_StringElements_DefinedSep)
321 {
322     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
323 
324     int32_t lengthArr = 10;
325     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
326     JSHandle<JSTaggedValue> handleTagValElementEcmaStr(objFactory->NewFromStdString("a"));
327     for (int i = 0; i < lengthArr; i++) {
328         handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue());
329     }
330     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
331     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
332     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
333     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
334     ecmaRuntimeCallInfo->SetCallArg(0,
335         JSHandle<JSTaggedValue>::Cast(objFactory->NewFromStdString(" <> ")).GetTaggedValue());
336     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
337     JSHandle<JSTaggedValue> handleTagValEcmaStrRet(thread,
338         JSStableArray::Join(handleArr, ecmaRuntimeCallInfo));
339     TestHelper::TearDownFrame(thread, prev);
340 
341     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
342     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(),
343         "a <> a <> a <> a <> a <> a <> a <> a <> a <> a");
344 }
345 }  // namespace panda::test