• 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/element_accessor.h"
17 #include "ecmascript/element_accessor-inl.h"
18 #include "ecmascript/js_stable_array.h"
19 #include "ecmascript/tests/test_helper.h"
20 
21 using namespace panda;
22 using namespace panda::ecmascript;
23 constexpr uint32_t ARRAY_LENGTH_4 = 4;
24 constexpr int32_t INT_VALUE_0 = 0;
25 constexpr int32_t INT_VALUE_1 = 1;
26 constexpr int32_t INT_VALUE_2 = 2;
27 constexpr int32_t INT_VALUE_3 = 3;
28 constexpr int32_t INT_VALUE_666 = 666;
29 
30 enum class StableArrayIndex {
31     STABLE_ARRAY_INDEX_0,
32     STABLE_ARRAY_INDEX_1,
33     STABLE_ARRAY_INDEX_2,
34     STABLE_ARRAY_INDEX_3
35 };
36 
37 namespace panda::test {
38 class JSStableArrayTest : public BaseTestWithScope<false> {
39 public:
CallJoin(JSHandle<TaggedArray> handleTagArr,std::string & sep,int64_t lengthArr) const40     JSHandle<JSTaggedValue> CallJoin(JSHandle<TaggedArray> handleTagArr, std::string& sep, int64_t lengthArr) const
41     {
42         ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory();
43         JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
44         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
45         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
46         ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
47         ecmaRuntimeCallInfo->SetCallArg(0,
48             JSHandle<JSTaggedValue>::Cast(objFactory->NewFromStdString(sep)).GetTaggedValue());
49         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
50         JSHandle<JSTaggedValue> sepHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromStdString(sep));
51         JSHandle<EcmaString> sepStringHandle = JSTaggedValue::ToString(thread, sepHandle);
52         JSHandle<JSTaggedValue> handleTagValEcmaStrRet(thread,
53             JSStableArray::Join(thread, handleArr, sepStringHandle, lengthArr));
54         TestHelper::TearDownFrame(thread, prev);
55         return handleTagValEcmaStrRet;
56     }
57 };
58 
59 /**
60  * @tc.name: Push
61  * @tc.desc: Change a JSArray through calling Push function with the JSArray and a EcmaRuntimeCallInfo, check whether
62  *           the TaggedArray of the JSArray is within expectations.
63  * @tc.type: FUNC
64  * @tc.require:
65  */
HWTEST_F_L0(JSStableArrayTest,Push)66 HWTEST_F_L0(JSStableArrayTest, Push)
67 {
68     int32_t lengthArr = 99;
69     int32_t numElementsPush = 9;
70     JSHandle<JSTaggedValue> handleTagValArr = JSArray::ArrayCreate(thread, JSTaggedNumber(lengthArr));
71     JSHandle<JSArray> handleArr(handleTagValArr);
72 
73     auto ecmaRuntimeCallInfo =
74         TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4 + 2 * numElementsPush);
75     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
76     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
77     for (int32_t i = 0; i < numElementsPush; i++) {
78         ecmaRuntimeCallInfo->SetCallArg(i, JSTaggedValue(i));
79     }
80     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
81     EXPECT_EQ(JSStableArray::Push(handleArr, ecmaRuntimeCallInfo),
82               JSTaggedValue(lengthArr + numElementsPush));
83     TestHelper::TearDownFrame(thread, prev);
84 
85     JSHandle<JSObject> arrObjHandle(handleArr);
86     EXPECT_EQ(handleArr->GetArrayLength(), static_cast<size_t>(lengthArr + numElementsPush));
87     for (int32_t i = lengthArr; i < lengthArr + numElementsPush; i++) {
88         EXPECT_EQ(ElementAccessor::Get(arrObjHandle, i).GetNumber(), i - lengthArr);
89     }
90 }
91 
92 /**
93  * @tc.name: Pop
94  * @tc.desc: Change a JSArray through calling Pop function with the JSArray and a EcmaRuntimeCallInfo, check whether
95  *           the JSArray and the TaggedArray of the JSArray are within expectations.
96  * @tc.type: FUNC
97  * @tc.require:
98  */
HWTEST_F_L0(JSStableArrayTest,Pop)99 HWTEST_F_L0(JSStableArrayTest, Pop)
100 {
101     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
102 
103     int32_t lengthArr = 49;
104     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
105     for (int i = 0; i < lengthArr; i++) {
106         handleTagArr->Set(thread, i, JSTaggedValue(i));
107     }
108     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
109 
110     for (int32_t i = 1; i < 6; i++) {
111         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
112         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
113         ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
114         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
115         EXPECT_EQ(JSStableArray::Pop(handleArr, ecmaRuntimeCallInfo), JSTaggedValue(lengthArr - i));
116         TestHelper::TearDownFrame(thread, prev);
117 
118         EXPECT_EQ(handleArr->GetArrayLength(), static_cast<uint32_t>(lengthArr - i));
119         if (i != 5) {
120             EXPECT_EQ(handleTagArr->GetLength(), static_cast<uint32_t>(lengthArr));
121             EXPECT_EQ(handleTagArr->Get(lengthArr - i), JSTaggedValue::Hole());
122         } else {
123             EXPECT_EQ(handleTagArr->GetLength(), static_cast<uint32_t>(lengthArr - i));
124         }
125     }
126 }
127 
128 /**
129  * @tc.name: Splice
130  * @tc.desc: Create a source TaggedArray, set value for the elements of the source TaggedArray, create an source Array
131  *           through calling CreateArrayFromList function with the source TaggedArray, create a deleted Array through
132  *           calling Splice function with the source Array, an EcmaRuntimeCallInfo that set Args from 2 as the
133  *           delete-elements, the offsetStartInsert, the countInsert and the actualDeleteCount. Check whether the
134  *           deleted Array and the source Array after change are within expectations.
135  * @tc.type: FUNC
136  * @tc.require:
137  */
HWTEST_F_L0(JSStableArrayTest,Splice)138 HWTEST_F_L0(JSStableArrayTest, Splice)
139 {
140     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
141 
142     int32_t lengthArr = 49;
143 
144     JSHandle<JSTaggedValue> handleTagValInsertElement1(thread, JSTaggedValue(4000));
145     JSHandle<JSTaggedValue> handleTagValInsertElement2(thread, JSTaggedValue(4100));
146     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
147     for (int i = 0; i < lengthArr; i++) {
148         handleTagArr->Set(thread, i, JSTaggedValue(i * 10));
149     }
150     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
151     double offsetStartInsert = 40;
152     double actualDeleteCount = 3;
153     double countInsert = 2;
154 
155     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(),
156         4 + (2 + countInsert) * 2);
157     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
158     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
159     ecmaRuntimeCallInfo->SetCallArg(2, handleTagValInsertElement1.GetTaggedValue());
160     ecmaRuntimeCallInfo->SetCallArg(3, handleTagValInsertElement2.GetTaggedValue());
161 
162     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
163     JSHandle<JSObject> thisObjHandle(handleArr);
164     JSTaggedValue newArray = JSArray::ArraySpeciesCreate(thread, thisObjHandle,
165                                                          JSTaggedNumber(static_cast<double>(actualDeleteCount)));
166     JSHandle<JSObject> newArrayHandle(thread, newArray);
167     uint32_t len = JSHandle<JSArray>::Cast(thisObjHandle)->GetArrayLength();
168     JSHandle<JSTaggedValue> handleTagValArrCombinedOfDeletedElements(thread,
169         JSStableArray::Splice(JSHandle<JSArray>::Cast(thisObjHandle), ecmaRuntimeCallInfo, offsetStartInsert,
170             countInsert, actualDeleteCount, newArrayHandle, len));
171     TestHelper::TearDownFrame(thread, prev);
172     JSHandle<JSArray> handleArrCombinedOfDeletedElements(handleTagValArrCombinedOfDeletedElements);
173     EXPECT_EQ(handleArrCombinedOfDeletedElements->GetArrayLength(), actualDeleteCount);
174     JSHandle<JSObject> handleObjArrCombinedOfDeletedElements(handleTagValArrCombinedOfDeletedElements);
175     for (int32_t i = 0; i < actualDeleteCount; i++) {
176         EXPECT_EQ(ElementAccessor::Get(handleObjArrCombinedOfDeletedElements, i).GetNumber(),
177                   (offsetStartInsert + i) * 10);
178     }
179 
180     // Check the JSArray(in-out-parameter) changed through calling the Splice function.
181     EXPECT_EQ(handleArr->GetArrayLength(), lengthArr - actualDeleteCount + countInsert);
182     for (int32_t i = 0; i < offsetStartInsert; i++) {
183         EXPECT_EQ(handleTagArr->Get(i).GetNumber(), i * 10);
184     }
185     EXPECT_EQ(handleTagArr->Get(offsetStartInsert).GetNumber(),
186               handleTagValInsertElement1.GetTaggedValue().GetNumber());
187     EXPECT_EQ(handleTagArr->Get(offsetStartInsert + 1).GetNumber(),
188               handleTagValInsertElement2.GetTaggedValue().GetNumber());
189     for (int32_t i = offsetStartInsert + countInsert; i < lengthArr - actualDeleteCount + countInsert; i++) {
190         EXPECT_EQ(handleTagArr->Get(i).GetNumber(), (i + actualDeleteCount - countInsert) * 10);
191     }
192 }
193 
194 /**
195  * @tc.name: Shift
196  * @tc.desc: Create a source Array, set value for the elements of the source Array, call the Shift function with the
197  *           source Array 5 times, check whether the returned JSTaggedValue and the changed source Array are within
198  *           expectations after each call to the Shift function.
199  * @tc.type: FUNC
200  * @tc.require:
201  */
HWTEST_F_L0(JSStableArrayTest,Shift)202 HWTEST_F_L0(JSStableArrayTest, Shift)
203 {
204     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
205 
206     int32_t lengthArr = 49;
207     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
208     for (int i = 0; i < lengthArr; i++) {
209         handleTagArr->Set(thread, i, JSTaggedValue(i * 10));
210     }
211     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
212 
213     for (int32_t i = 0; i < 5; i++) {
214         auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
215         ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
216         ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
217         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
218         EXPECT_EQ(JSStableArray::Shift(handleArr, ecmaRuntimeCallInfo), JSTaggedValue(i * 10));
219         TestHelper::TearDownFrame(thread, prev);
220         EXPECT_EQ(handleArr->GetArrayLength(), static_cast<uint32_t>(lengthArr - (i + 1)));
221         EXPECT_EQ(handleTagArr->Get(0), JSTaggedValue((i + 1) * 10));
222         if (i != 4) {
223             EXPECT_EQ(handleTagArr->GetLength(), static_cast<uint32_t>(lengthArr));
224             EXPECT_EQ(handleTagArr->Get(lengthArr - (i + 1)), JSTaggedValue::Hole());
225             continue;
226         }
227         EXPECT_EQ(handleTagArr->GetLength(), static_cast<uint32_t>(lengthArr - (i + 1)));
228     }
229 }
230 
231 /**
232  * @tc.name: Join_NumberElements_UndefinedSep
233  * @tc.desc: Create a source Array whose elements are Numbers and an EcmaRuntimeCallInfo, check whether the EcmaString
234  *           returned through calling Join function with the source Array and the EcmaRuntimeCallInfo is within
235  *           expectations.
236  * @tc.type: FUNC
237  * @tc.require:
238  */
HWTEST_F_L0(JSStableArrayTest,Join_NumberElements_UndefinedSep)239 HWTEST_F_L0(JSStableArrayTest, Join_NumberElements_UndefinedSep)
240 {
241     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
242 
243     int32_t lengthArr = 10;
244     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
245     for (int i = 0; i < lengthArr; i++) {
246         handleTagArr->Set(thread, i, JSTaggedValue(i));
247     }
248     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
249     std::vector<JSTaggedValue> args{};
250     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 4);
251     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
252     JSHandle<JSTaggedValue> sepHandle = thread->GlobalConstants()->GetHandledCommaString();
253     JSHandle<EcmaString> sepStringHandle = JSTaggedValue::ToString(thread, sepHandle);
254     JSHandle<JSTaggedValue> handleTagValEcmaStrRet(thread,
255         JSStableArray::Join(thread, handleArr, sepStringHandle, lengthArr));
256     TestHelper::TearDownFrame(thread, prev);
257 
258     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
259     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), "0,1,2,3,4,5,6,7,8,9");
260     EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString());
261 }
262 
263 /**
264  * @tc.name: Join_StringElements_UndefinedSep
265  * @tc.desc: Create a source Array whose elements are EcmaStrings and an EcmaRuntimeCallInfo, check whether the
266  *           EcmaString returned through calling Join function with the source Array and the EcmaRuntimeCallInfo is
267  *           within expectations.
268  * @tc.type: FUNC
269  * @tc.require:
270  */
HWTEST_F_L0(JSStableArrayTest,Join_StringElements_UndefinedSep)271 HWTEST_F_L0(JSStableArrayTest, Join_StringElements_UndefinedSep)
272 {
273     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
274 
275     int32_t lengthArr = 10;
276     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
277     JSHandle<JSTaggedValue> handleTagValElementEcmaStr(objFactory->NewFromStdString("abc"));
278     for (int i = 0; i < lengthArr; i++) {
279         handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue());
280     }
281     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
282     std::vector<JSTaggedValue> args{};
283     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 4);
284     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
285     JSHandle<JSTaggedValue> sepHandle = thread->GlobalConstants()->GetHandledCommaString();
286     JSHandle<EcmaString> sepStringHandle = JSTaggedValue::ToString(thread, sepHandle);
287     JSHandle<JSTaggedValue> handleTagValEcmaStrRet(thread,
288         JSStableArray::Join(thread, handleArr, sepStringHandle, lengthArr));
289     TestHelper::TearDownFrame(thread, prev);
290 
291     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
292     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), "abc,abc,abc,abc,abc,abc,abc,abc,abc,abc");
293     EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString());
294 }
295 
296 /**
297  * @tc.name: Join_NumberElements_DefinedSep
298  * @tc.desc: Create a source Array whose elements are Numbers and an EcmaRuntimeCallInfo, define the first arg of the
299              EcmaRuntimeCallInfo an EcmaString as the seperator, check whether the EcmaString returned through calling
300              Join function with the source Array and the EcmaRuntimeCallInfo is within expectations.
301  * @tc.type: FUNC
302  * @tc.require:
303  */
HWTEST_F_L0(JSStableArrayTest,Join_NumberElements_DefinedSep)304 HWTEST_F_L0(JSStableArrayTest, Join_NumberElements_DefinedSep)
305 {
306     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
307 
308     int32_t lengthArr = 10;
309     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
310     for (int i = 0; i < lengthArr; i++) {
311         handleTagArr->Set(thread, i, JSTaggedValue(i));
312     }
313     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
314     std::vector<JSTaggedValue> args{JSHandle<JSTaggedValue>::Cast(objFactory->NewFromStdString("^")).GetTaggedValue()};
315     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 6);
316     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
317     JSHandle<JSTaggedValue> sepHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromStdString("^"));
318     JSHandle<EcmaString> sepStringHandle = JSTaggedValue::ToString(thread, sepHandle);
319     JSHandle<JSTaggedValue> handleTagValEcmaStrRet(thread,
320         JSStableArray::Join(thread, handleArr, sepStringHandle, lengthArr));
321     TestHelper::TearDownFrame(thread, prev);
322 
323     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
324     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), "0^1^2^3^4^5^6^7^8^9");
325     EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString());
326 }
327 
328 /**
329  * @tc.name: Join_StringElements_DefinedSep
330  * @tc.desc: Create a source Array whose elements are EcmaStrings and an EcmaRuntimeCallInfo, define the first arg of
331              the EcmaRuntimeCallInfo an EcmaString as the seperator, check whether the EcmaString returned through
332              calling Join function with the source Array and the EcmaRuntimeCallInfo is within expectations.
333  * @tc.type: FUNC
334  * @tc.require:
335  */
HWTEST_F_L0(JSStableArrayTest,Join_StringElements_DefinedSep)336 HWTEST_F_L0(JSStableArrayTest, Join_StringElements_DefinedSep)
337 {
338     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
339 
340     int32_t lengthArr = 10;
341     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
342     JSHandle<JSTaggedValue> handleTagValElementEcmaStr(objFactory->NewFromStdString("a"));
343     for (int i = 0; i < lengthArr; i++) {
344         handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue());
345     }
346     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
347     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
348     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
349     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
350     ecmaRuntimeCallInfo->SetCallArg(0,
351         JSHandle<JSTaggedValue>::Cast(objFactory->NewFromStdString(" <> ")).GetTaggedValue());
352     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
353     JSHandle<JSTaggedValue> sepHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromStdString(" <> "));
354     JSHandle<EcmaString> sepStringHandle = JSTaggedValue::ToString(thread, sepHandle);
355     JSHandle<JSTaggedValue> handleTagValEcmaStrRet(thread,
356         JSStableArray::Join(thread, handleArr, sepStringHandle, lengthArr));
357     TestHelper::TearDownFrame(thread, prev);
358 
359     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
360     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(),
361         "a <> a <> a <> a <> a <> a <> a <> a <> a <> a");
362     EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString());
363 }
364 
365 /**
366  * @tc.name: Join_StringElements_ManyTiny
367  * @tc.desc: Create a source Array whose elements are EcmaStrings and an EcmaRuntimeCallInfo, define the first arg of
368              the EcmaRuntimeCallInfo an EcmaString as the seperator, check whether the EcmaString returned through
369              calling Join function with the source Array and the EcmaRuntimeCallInfo is within expectations.
370  * @tc.type: FUNC
371  * @tc.require:
372  */
HWTEST_F_L0(JSStableArrayTest,Join_StringElements_ManyTiny)373 HWTEST_F_L0(JSStableArrayTest, Join_StringElements_ManyTiny)
374 {
375     int32_t lengthArr = 256;
376     std::string sep = "";
377     // tiny string join should not use tree string.
378     ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory();
379     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
380     JSHandle<JSTaggedValue> handleTagValElementEcmaStr(objFactory->NewFromStdString("a"));
381     for (int i = 0; i < lengthArr; i++) {
382         handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue());
383     }
384     JSHandle<JSTaggedValue> handleTagValEcmaStrRet = CallJoin(handleTagArr, sep, lengthArr);
385     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
386     // 256 x a
387     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(),
388                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
389                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
390                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
391                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
392     EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString());
393     sep = ",";
394     handleTagValEcmaStrRet = CallJoin(handleTagArr, sep, lengthArr);
395     JSHandle<EcmaString> handleEcmaStrRet2(handleTagValEcmaStrRet);
396     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet2).ToCString().c_str(),
397                  "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,"
398                  "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,"
399                  "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,"
400                  "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,"
401                  "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,"
402                  "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,"
403                  "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,"
404                  "a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a");
405     EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrRet2).IsTreeString());
406 }
407 
408 /**
409  * @tc.name: Join_StringElements_ManyTiny
410  * @tc.desc: Create a source Array whose elements are EcmaStrings and an EcmaRuntimeCallInfo, define the first arg of
411              the EcmaRuntimeCallInfo an EcmaString as the seperator, check whether the EcmaString returned through
412              calling Join function with the source Array and the EcmaRuntimeCallInfo is within expectations.
413  * @tc.type: FUNC
414  * @tc.require:
415  */
HWTEST_F_L0(JSStableArrayTest,Join_StringElements_LargeString)416 HWTEST_F_L0(JSStableArrayTest, Join_StringElements_LargeString)
417 {
418     int32_t lengthArr = 8;
419     std::string sep = "";
420     // large string should use tree string.
421     ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory();
422     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
423     // 32 x a
424     JSHandle<JSTaggedValue>
425         handleTagValElementEcmaStr(objFactory->NewFromStdString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
426     for (int i = 0; i < lengthArr; i++) {
427         handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue());
428     }
429     JSHandle<JSTaggedValue> handleTagValEcmaStrRet = CallJoin(handleTagArr, sep, lengthArr);
430     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
431     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(),
432                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
433                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
434                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
435                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
436     EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString());
437 }
438 
439 /**
440 * @tc.name: Join_StringElements_ManyTiny
441 * @tc.desc: Create a source Array whose elements are EcmaStrings and an EcmaRuntimeCallInfo, define the first arg of
442          the EcmaRuntimeCallInfo an EcmaString as the seperator, check whether the EcmaString returned through
443          calling Join function with the source Array and the EcmaRuntimeCallInfo is within expectations.
444 * @tc.type: FUNC
445 * @tc.require:
446 */
HWTEST_F_L0(JSStableArrayTest,Join_StringElements_LargeString2)447 HWTEST_F_L0(JSStableArrayTest, Join_StringElements_LargeString2)
448 {
449     int32_t lengthArr = 4;
450     std::string sep = ",";
451     // large string should use tree string.
452     ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory();
453     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
454     // 64 x a
455     JSHandle<JSTaggedValue> handleTagValElementEcmaStr(
456         objFactory->NewFromStdString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
457     for (int i = 0; i < lengthArr; i++) {
458         handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue());
459     }
460     JSHandle<JSTaggedValue> handleTagValEcmaStrRet = CallJoin(handleTagArr, sep, lengthArr);
461 
462     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
463     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(),
464                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,"
465                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,"
466                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,"
467                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
468     EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString());
469 }
470 
471 /**
472 * @tc.name: Join_StringElements_ManyTiny
473 * @tc.desc: Create a source Array whose elements are EcmaStrings and an EcmaRuntimeCallInfo, define the first arg of
474          the EcmaRuntimeCallInfo an EcmaString as the seperator, check whether the EcmaString returned through
475          calling Join function with the source Array and the EcmaRuntimeCallInfo is within expectations.
476 * @tc.type: FUNC
477 * @tc.require:
478 */
HWTEST_F_L0(JSStableArrayTest,Join_StringElements_LargeString3)479 HWTEST_F_L0(JSStableArrayTest, Join_StringElements_LargeString3)
480 {
481     int32_t lengthArr = 5;
482     std::string sep = ",";
483     // large string should use tree string.
484     ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory();
485     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
486     // 64 x a
487     JSHandle<JSTaggedValue> handleTagValElementEcmaStr0(
488         objFactory->NewFromStdString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
489     handleTagArr->Set(thread, 0, handleTagValElementEcmaStr0.GetTaggedValue());
490     JSHandle<JSTaggedValue> handleTagValElementEcmaStr1(
491         objFactory->NewFromStdString("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"));
492     handleTagArr->Set(thread, 1, handleTagValElementEcmaStr1.GetTaggedValue());
493     JSHandle<JSTaggedValue> handleTagValElementEcmaStr2(
494         objFactory->NewFromStdString("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"));
495     handleTagArr->Set(thread, 2, handleTagValElementEcmaStr2.GetTaggedValue());
496     JSHandle<JSTaggedValue> handleTagValElementEcmaStr3(
497         objFactory->NewFromStdString("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"));
498     handleTagArr->Set(thread, 3, handleTagValElementEcmaStr3.GetTaggedValue());
499     JSHandle<JSTaggedValue> handleTagValElementEcmaStr4(
500         objFactory->NewFromStdString("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"));
501     handleTagArr->Set(thread, 4, handleTagValElementEcmaStr4.GetTaggedValue());
502 
503     JSHandle<JSTaggedValue> handleTagValEcmaStrRet = CallJoin(handleTagArr, sep, lengthArr);
504 
505     JSHandle<EcmaString> handleEcmaStrRet(handleTagValEcmaStrRet);
506     EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(),
507                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,"
508                  "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,"
509                  "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc,"
510                  "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd,"
511                  "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
512     EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString());
513 }
514 
515 /**
516  * @tc.name: At
517  * @tc.desc: Create a source Array whose elements are Numbers and an EcmaRuntimeCallInfo, define the first arg of the
518              EcmaRuntimeCallInfo an number as the index, check whether the element returned through calling
519              At function with the source Array and the EcmaRuntimeCallInfo is within expectations.
520  * @tc.type: FUNC
521  * @tc.require:
522  */
HWTEST_F_L0(JSStableArrayTest,At_NUMBER_INDEX)523 HWTEST_F_L0(JSStableArrayTest, At_NUMBER_INDEX)
524 {
525     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
526 
527     int32_t lengthArr = 10;
528     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
529     for (int i = 0; i < lengthArr; i++) {
530         handleTagArr->Set(thread, i, JSTaggedValue(i));
531     }
532     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
533     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
534     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
535     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
536     ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(0));
537     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
538 
539     JSTaggedValue thisTagValue = JSStableArray::At(handleArr, ecmaRuntimeCallInfo);
540     TestHelper::TearDownFrame(thread, prev);
541 
542     EXPECT_EQ(thisTagValue.GetNumber(), 0);
543 
544     ecmaRuntimeCallInfo  = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
545     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
546     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
547     ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(9));
548     prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
549 
550     thisTagValue = JSStableArray::At(handleArr, ecmaRuntimeCallInfo);
551     TestHelper::TearDownFrame(thread, prev);
552 
553     EXPECT_EQ(thisTagValue.GetNumber(), 9);
554 
555     ecmaRuntimeCallInfo  = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
556     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
557     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
558     ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(-1));
559     prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
560 
561     thisTagValue = JSStableArray::At(handleArr, ecmaRuntimeCallInfo);
562     TestHelper::TearDownFrame(thread, prev);
563 
564     EXPECT_EQ(thisTagValue.GetNumber(), 9);
565 
566     ecmaRuntimeCallInfo  = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
567     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
568     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
569     ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(10));
570     prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
571 
572     thisTagValue = JSStableArray::At(handleArr, ecmaRuntimeCallInfo);
573     TestHelper::TearDownFrame(thread, prev);
574 
575     EXPECT_EQ(thisTagValue, JSTaggedValue::Undefined());
576 }
577 
578 /**
579  * @tc.name: With
580  * @tc.desc: Create a source Array whose elements are Numbers, define the first arg a thread,
581  *           define the second arg as the source Array, define the third arg an number as the length of source Array
582  *           define the forth arg an number as the index, define the fifth args an number as the value
583  *           check whether the value returned through calling With function with the source Array
584  *           and the args is within expectations.
585  * @tc.type: FUNC
586  * @tc.require:
587  */
HWTEST_F_L0(JSStableArrayTest,With)588 HWTEST_F_L0(JSStableArrayTest, With)
589 {
590     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
591     int32_t lengthArr = ARRAY_LENGTH_4;
592     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
593     for (int i = 0; i < lengthArr; i++) {
594         handleTagArr->Set(thread, i, JSTaggedValue(i));
595     }
596     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
597 
598     int64_t arrayLength = ARRAY_LENGTH_4;
599     int64_t index = static_cast<int64_t>(StableArrayIndex::STABLE_ARRAY_INDEX_2);
600     JSTaggedValue resultArr = JSStableArray::With(thread, handleArr,
601                                                   arrayLength, index,
602                                                   JSHandle<JSTaggedValue>(thread, JSTaggedValue(INT_VALUE_666)));
603     JSHandle<JSTaggedValue> destTaggedValue(thread, resultArr);
604     JSHandle<JSArray> destArr(destTaggedValue);
605     JSHandle<TaggedArray> destTaggedArr(thread, TaggedArray::Cast(destArr->GetElements().GetTaggedObject()));
606     for (uint32_t i = 0; i < ARRAY_LENGTH_4; ++i) {
607         JSHandle<JSObject> arrObjHandle(handleArr);
608         EXPECT_EQ(ElementAccessor::Get(arrObjHandle, i).GetNumber(), i);
609     }
610     for (uint32_t i = 0; i < ARRAY_LENGTH_4; ++i) {
611         JSHandle<JSObject> arrObjHandle(destArr);
612         if (i == 2) {
613             EXPECT_EQ(ElementAccessor::Get(arrObjHandle, i).GetNumber(), INT_VALUE_666);
614         } else {
615             EXPECT_EQ(ElementAccessor::Get(arrObjHandle, i).GetNumber(), i);
616         }
617     }
618 }
619 
620 /**
621  * @tc.name: ToReversed
622  * @tc.desc: Create a source Array whose elements are Numbers and an EcmaRuntimeCallInfo, check whether the
623              value returned through calling ToReversed function with the source Array is within expectations.
624  * @tc.type: FUNC
625  * @tc.require:
626  */
HWTEST_F_L0(JSStableArrayTest,ToReversed)627 HWTEST_F_L0(JSStableArrayTest, ToReversed)
628 {
629     ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory();
630     int32_t lengthArr = ARRAY_LENGTH_4;
631     JSHandle<TaggedArray> handleTagArr(objFactory->NewTaggedArray(lengthArr));
632     for (int i = 0; i < lengthArr; i++) {
633         handleTagArr->Set(thread, i, JSTaggedValue(i));
634     }
635     JSHandle<JSArray> handleArr(JSArray::CreateArrayFromList(thread, handleTagArr));
636     JSHandle<JSObject> handleArrObj(handleArr);
637     JSTaggedValue resultArr =
638         JSStableArray::ToReversed(thread, handleArr, ARRAY_LENGTH_4);
639     JSHandle<JSObject> dstArrObj(thread, resultArr);
640 
641     EXPECT_EQ(ElementAccessor::Get(handleArrObj,
642         static_cast<uint32_t>(StableArrayIndex::STABLE_ARRAY_INDEX_0)).GetNumber(), INT_VALUE_0);
643     EXPECT_EQ(ElementAccessor::Get(handleArrObj,
644         static_cast<uint32_t>(StableArrayIndex::STABLE_ARRAY_INDEX_1)).GetNumber(), INT_VALUE_1);
645     EXPECT_EQ(ElementAccessor::Get(handleArrObj,
646         static_cast<uint32_t>(StableArrayIndex::STABLE_ARRAY_INDEX_2)).GetNumber(), INT_VALUE_2);
647     EXPECT_EQ(ElementAccessor::Get(handleArrObj,
648         static_cast<uint32_t>(StableArrayIndex::STABLE_ARRAY_INDEX_3)).GetNumber(), INT_VALUE_3);
649 
650     EXPECT_EQ(ElementAccessor::Get(dstArrObj,
651         static_cast<uint32_t>(StableArrayIndex::STABLE_ARRAY_INDEX_0)).GetNumber(), INT_VALUE_3);
652     EXPECT_EQ(ElementAccessor::Get(dstArrObj,
653         static_cast<uint32_t>(StableArrayIndex::STABLE_ARRAY_INDEX_1)).GetNumber(), INT_VALUE_2);
654     EXPECT_EQ(ElementAccessor::Get(dstArrObj,
655         static_cast<uint32_t>(StableArrayIndex::STABLE_ARRAY_INDEX_2)).GetNumber(), INT_VALUE_1);
656     EXPECT_EQ(ElementAccessor::Get(dstArrObj,
657         static_cast<uint32_t>(StableArrayIndex::STABLE_ARRAY_INDEX_3)).GetNumber(), INT_VALUE_0);
658 }
659 }  // namespace panda::test
660