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