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_api/js_api_plain_array.h" 17#include "ecmascript/containers/containers_private.h" 18#include "ecmascript/ecma_string.h" 19#include "ecmascript/ecma_vm.h" 20#include "ecmascript/global_env.h" 21#include "ecmascript/js_api/js_api_plain_array_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/tests/ecma_test_common.h" 29 30using namespace panda; 31 32using namespace panda::ecmascript; 33 34namespace panda::test { 35class JSAPIPlainArrayTest : public BaseTestWithScope<false> { 36protected: 37 JSAPIPlainArray *CreatePlainArray() 38 { 39 return EcmaContainerCommon::CreatePlainArray(thread); 40 } 41 JSHandle<JSAPIPlainArray> GetIndexOfKeyAndGeIndexOfValueGetArray(JSMutableHandle<JSTaggedValue>& value, 42 uint32_t numbers) 43 { 44 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 45 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 46 47 JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray()); 48 EXPECT_TRUE(array->IsEmpty()); 49 std::string myValue("myvalue"); 50 for (uint32_t i = 0; i < numbers; i++) { 51 uint32_t ikey = 100 + i; 52 std::string ivalue = myValue + std::to_string(i); 53 key.Update(JSTaggedValue(ikey)); 54 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 55 JSAPIPlainArray::Add(thread, array, key, value); 56 } 57 EXPECT_EQ(array->GetSize(), static_cast<int>(numbers)); 58 EXPECT_FALSE(array->IsEmpty()); 59 return array; 60 } 61 62 JSHandle<JSAPIPlainArray> PropertyCommon(uint32_t elementsNums) 63 { 64 JSHandle<JSAPIPlainArray> plainArray(thread, CreatePlainArray()); 65 for (uint32_t i = 0; i < elementsNums; i++) { 66 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i)); 67 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i)); 68 JSAPIPlainArray::Add(thread, plainArray, key, value); 69 } 70 return plainArray; 71 } 72}; 73 74HWTEST_F_L0(JSAPIPlainArrayTest, PlainArrayCreate) 75{ 76 JSAPIPlainArray *plainArray = CreatePlainArray(); 77 EXPECT_TRUE(plainArray != nullptr); 78} 79 80HWTEST_F_L0(JSAPIPlainArrayTest, PA_AddAndGetKeyAtAndClear) 81{ 82 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value 83 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 84 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 85 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 86 87 // test JSAPIPlainArray 88 JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray()); 89 std::string myValue("myvalue"); 90 for (uint32_t i = 0; i < NODE_NUMBERS; i = i + 2) { 91 uint32_t ikey = 100 + i; 92 std::string ivalue = myValue + std::to_string(i); 93 94 key.Update(JSTaggedValue(ikey)); 95 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 96 97 JSAPIPlainArray::Add(thread, array, key, value); 98 } 99 for (uint32_t i = 1; i < NODE_NUMBERS; i = i + 2) { 100 uint32_t ikey = 100 + i; 101 std::string ivalue = myValue + std::to_string(i); 102 103 key.Update(JSTaggedValue(ikey)); 104 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 105 106 JSAPIPlainArray::Add(thread, array, key, value); 107 } 108 EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS)); 109 110 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 111 uint32_t ikey = 100 + i; 112 std::string ivalue = myValue + std::to_string(i); 113 key.Update(JSTaggedValue(ikey)); 114 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 115 116 // test getKeyAt 117 JSTaggedValue gvalue = array->GetKeyAt(i); 118 EXPECT_EQ(gvalue, key.GetTaggedValue()); 119 } 120 EXPECT_EQ(array->GetKeyAt(-1), JSTaggedValue::Undefined()); 121 EXPECT_EQ(array->GetKeyAt(NODE_NUMBERS), JSTaggedValue::Undefined()); 122 // test clear 123 array->Clear(thread); 124 EXPECT_EQ(array->GetSize(), 0); // 0 means the value 125} 126 127HWTEST_F_L0(JSAPIPlainArrayTest, PA_CloneAndHasAndGet) 128{ 129 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value 130 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 131 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 132 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 133 134 // test JSAPIPlainArray 135 JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray()); 136 std::string myValue("myvalue"); 137 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 138 uint32_t ikey = 100 + i; 139 std::string ivalue = myValue + std::to_string(i); 140 key.Update(JSTaggedValue(ikey)); 141 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 142 JSAPIPlainArray::Add(thread, array, key, value); 143 } 144 EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS)); 145 146 // test clone 147 JSHandle<JSAPIPlainArray> newArray(thread, CreatePlainArray()); 148 EXPECT_EQ(newArray->GetSize(), 0); // 0 means the value 149 newArray = JSAPIPlainArray::Clone(thread, array); 150 EXPECT_EQ(newArray->GetSize(), static_cast<int>(NODE_NUMBERS)); 151 152 // test has 153 key.Update(JSTaggedValue(103)); // 103 means the value 154 int32_t lkey = 103; 155 bool result = array->Has(lkey); 156 EXPECT_TRUE(result); 157 EXPECT_FALSE(array->Has(lkey * 2)); 158 159 // test get 160 myValue = std::string("myvalue3"); 161 value.Update(factory->NewFromStdString(myValue).GetTaggedValue()); 162 EXPECT_TRUE(JSTaggedValue::Equal(thread, JSHandle<JSTaggedValue>(thread, array->Get(key.GetTaggedValue())), value)); 163} 164 165HWTEST_F_L0(JSAPIPlainArrayTest, PA_GetIndexOfKeyAndGeIndexOfValueAndIsEmptyAndRemoveRangeFrom) 166{ 167 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value 168 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 169 auto array = GetIndexOfKeyAndGeIndexOfValueGetArray(value, NODE_NUMBERS); 170 value.Update(JSTaggedValue(103)); // 103 means the value 171 int32_t lvalue = 103; 172 JSTaggedValue value2 = array->GetIndexOfKey(lvalue); 173 EXPECT_EQ(value2.GetNumber(), 3); // 3 means the value 174 EXPECT_EQ(array->GetIndexOfKey(lvalue * 2), JSTaggedValue(-1)); 175 176 std::string myValue = "myvalue2"; 177 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 178 value.Update(factory->NewFromStdString(myValue).GetTaggedValue()); 179 JSTaggedValue value3 = array->GetIndexOfValue(value.GetTaggedValue()); 180 EXPECT_EQ(value3.GetNumber(), 2); // 2 means the value 181 EXPECT_EQ(array->GetIndexOfValue(JSTaggedValue(0)), JSTaggedValue(-1)); 182 183 value.Update(JSTaggedValue(1)); 184 int32_t batchSize = 3; // 3 means the value 185 lvalue = 1; 186 value3 = array->RemoveRangeFrom(thread, lvalue, batchSize); 187 EXPECT_EQ(value3.GetNumber(), 3); // 3 means the value 188 EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 3)); 189 190 // test RemoveRangeFrom exception 191 array->RemoveRangeFrom(thread, lvalue, -1); 192} 193 194HWTEST_F_L0(JSAPIPlainArrayTest, PA_RemvoeAnrRemvoeAtAndSetValueAtAndGetValueAt) 195{ 196 constexpr uint32_t NODE_NUMBERS = 8; // 8 means the value 197 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 198 auto array = GetIndexOfKeyAndGeIndexOfValueGetArray(value, NODE_NUMBERS); 199 // test Remove 200 std::string myValue = "myvalue2"; 201 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 202 value.Update(factory->NewFromStdString(myValue).GetTaggedValue()); 203 JSTaggedValue taggedValue = 204 array->Remove(thread, JSTaggedValue(102)); // 102 means the value 205 EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue))); 206 EXPECT_EQ(array->Remove(thread, JSTaggedValue(-1)), JSTaggedValue::Undefined()); 207 EXPECT_EQ(array->Remove(thread, JSTaggedValue(100 + NODE_NUMBERS)), JSTaggedValue::Undefined()); 208 209 // test RemoveAt 210 myValue = "myvalue4"; 211 value.Update(factory->NewFromStdString(myValue).GetTaggedValue()); 212 taggedValue = 213 array->RemoveAt(thread, JSTaggedValue(3)); // 3 means the value 214 EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue))); 215 EXPECT_EQ(array->GetSize(), static_cast<int>(NODE_NUMBERS - 2)); 216 EXPECT_EQ(array->RemoveAt(thread, JSTaggedValue(-1)), JSTaggedValue::Undefined()); 217 EXPECT_EQ(array->RemoveAt(thread, JSTaggedValue(NODE_NUMBERS)), JSTaggedValue::Undefined()); 218 219 // test SetValueAt 220 myValue = "myvalue14"; 221 value.Update(factory->NewFromStdString(myValue).GetTaggedValue()); 222 array->SetValueAt(thread, JSTaggedValue(3), value.GetTaggedValue()); // 3 means the value 223 int32_t lvalue = 3; // 3 means the value 224 taggedValue = array->GetValueAt(thread, lvalue); 225 EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle<JSTaggedValue>(thread, taggedValue))); 226} 227 228HWTEST_F_L0(JSAPIPlainArrayTest, PA_GetOwnProperty) 229{ 230 constexpr uint32_t DEFAULT_LENGTH = 8; 231 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 232 JSHandle<JSAPIPlainArray> toor(thread, CreatePlainArray()); 233 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 234 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 235 236 std::string plainArrayvalue("plainArrayvalue"); 237 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) { 238 uint32_t ikey = 100 + i; 239 std::string ivalue = plainArrayvalue + std::to_string(i); 240 key.Update(JSTaggedValue(ikey)); 241 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 242 JSAPIPlainArray::Add(thread, toor, key, value); 243 } 244 // test GetOwnProperty 245 int testInt = 100 + 1; 246 JSHandle<JSTaggedValue> plainArrayKey1(thread, JSTaggedValue(testInt)); 247 EXPECT_TRUE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey1)); 248 testInt = 100 + 20; 249 JSHandle<JSTaggedValue> plainArrayKey2(thread, JSTaggedValue(testInt)); 250 EXPECT_FALSE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey2)); 251} 252 253HWTEST_F_L0(JSAPIPlainArrayTest, PA_ToString) 254{ 255 constexpr uint32_t NODE_NUMBERS = 3; // 3 means the value 256 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 257 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 258 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 259 260 // test JSAPIPlainArray 261 JSHandle<JSAPIPlainArray> array(thread, CreatePlainArray()); 262 JSTaggedValue result1 = JSAPIPlainArray::ToString(thread, array); 263 JSHandle<EcmaString> resultHandle1(thread, result1); 264 JSHandle<EcmaString> det = thread->GetEcmaVM()->GetFactory()->NewFromASCII(""); 265 ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle1, det), 0); 266 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 267 uint32_t ikey = i; 268 std::string ivalue = std::to_string(i); 269 key.Update(JSTaggedValue(ikey)); 270 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 271 JSAPIPlainArray::Add(thread, array, key, value); 272 } 273 JSHandle<EcmaString> str = thread->GetEcmaVM()->GetFactory()->NewFromASCII("0:0,1:1,2:2"); 274 JSTaggedValue result = JSAPIPlainArray::ToString(thread, array); 275 JSHandle<EcmaString> resultHandle(thread, result); 276 277 ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, str), 0); 278} 279 280/** 281 * @tc.name: GetProperty 282 * @tc.desc: 283 * @tc.type: FUNC 284 * @tc.require: 285 */ 286HWTEST_F_L0(JSAPIPlainArrayTest, GetProperty) 287{ 288 uint32_t elementsNums = 8; 289 auto plainArray = PropertyCommon(elementsNums); 290 for (uint32_t i = 0; i < elementsNums; i++) { 291 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i)); 292 OperationResult getPropertyRes = JSAPIPlainArray::GetProperty(thread, plainArray, key); 293 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i)); 294 } 295} 296 297/** 298 * @tc.name: SetProperty 299 * @tc.desc: 300 * @tc.type: FUNC 301 * @tc.require: 302 */ 303HWTEST_F_L0(JSAPIPlainArrayTest, SetProperty) 304{ 305 uint32_t elementsNums = 8; 306 auto plainArray = PropertyCommon(elementsNums); 307 for (uint32_t i = 0; i < elementsNums; i++) { 308 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i)); 309 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double 310 bool setPropertyRes = JSAPIPlainArray::SetProperty(thread, plainArray, key, value); 311 EXPECT_EQ(setPropertyRes, true); 312 } 313 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1)); 314 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1)); 315 EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key, value)); 316 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums)); 317 EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key1, value)); 318 JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(int64_t(-9007199254740992))); // Out-of-Bounds test 319 EXPECT_FALSE(JSAPIPlainArray::SetProperty(thread, plainArray, key1, value)); 320} 321} // namespace panda::test 322