1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "ecmascript/containers/containers_private.h" 17 #include "ecmascript/ecma_string.h" 18 #include "ecmascript/ecma_vm.h" 19 #include "ecmascript/global_env.h" 20 #include "ecmascript/js_api/js_api_stack.h" 21 #include "ecmascript/js_api/js_api_stack_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/test_helper.h" 29 30 using namespace panda; 31 32 using namespace panda::ecmascript; 33 34 using namespace panda::ecmascript::containers; 35 36 namespace panda::test { 37 class JSAPIStackTest : public testing::Test { 38 public: SetUpTestCase()39 static void SetUpTestCase() 40 { 41 GTEST_LOG_(INFO) << "SetUpTestCase"; 42 } 43 TearDownTestCase()44 static void TearDownTestCase() 45 { 46 GTEST_LOG_(INFO) << "TearDownCase"; 47 } 48 SetUp()49 void SetUp() override 50 { 51 TestHelper::CreateEcmaVMWithScope(instance, thread, scope); 52 } 53 TearDown()54 void TearDown() override 55 { 56 TestHelper::DestroyEcmaVMWithScope(instance, scope); 57 } 58 59 EcmaVM *instance {nullptr}; 60 ecmascript::EcmaHandleScope *scope {nullptr}; 61 JSThread *thread {nullptr}; 62 63 protected: CreateStack()64 JSAPIStack *CreateStack() 65 { 66 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 67 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 68 69 JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject(); 70 JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate")); 71 JSHandle<JSTaggedValue> value = 72 JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue(); 73 74 auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); 75 objCallInfo->SetFunction(JSTaggedValue::Undefined()); 76 objCallInfo->SetThis(value.GetTaggedValue()); 77 objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(containers::ContainerTag::Stack))); 78 79 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo); 80 JSTaggedValue result = containers::ContainersPrivate::Load(objCallInfo); 81 TestHelper::TearDownFrame(thread, prev); 82 83 JSHandle<JSTaggedValue> constructor(thread, result); 84 JSHandle<JSAPIStack> stack(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor)); 85 stack->SetTop(-1); 86 return *stack; 87 } 88 }; 89 HWTEST_F_L0(JSAPIStackTest,stackCreate)90 HWTEST_F_L0(JSAPIStackTest, stackCreate) 91 { 92 JSAPIStack *stack = CreateStack(); 93 EXPECT_TRUE(stack != nullptr); 94 } 95 HWTEST_F_L0(JSAPIStackTest,PushAndPeek)96 HWTEST_F_L0(JSAPIStackTest, PushAndPeek) 97 { 98 constexpr uint32_t NODE_NUMBERS = 9; 99 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 100 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 101 102 JSHandle<JSAPIStack> toor(thread, CreateStack()); 103 104 // test Peek empty 105 EXPECT_EQ(toor->Peek(), JSTaggedValue::Undefined()); 106 107 std::string myValue("myvalue"); 108 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 109 std::string ivalue = myValue + std::to_string(i); 110 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 111 JSTaggedValue result = JSAPIStack::Push(thread, toor, value); 112 EXPECT_EQ(result, value.GetTaggedValue()); 113 EXPECT_EQ(toor->Peek(), value.GetTaggedValue()); 114 } 115 EXPECT_EQ(static_cast<uint32_t>(toor->GetTop() + 1), NODE_NUMBERS); 116 117 toor->Dump(); 118 } 119 HWTEST_F_L0(JSAPIStackTest,Pop)120 HWTEST_F_L0(JSAPIStackTest, Pop) 121 { 122 constexpr uint32_t NODE_NUMBERS = 9; 123 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 124 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 125 126 JSHandle<JSAPIStack> toor(thread, CreateStack()); 127 128 // test Pop empty 129 EXPECT_EQ(toor->Pop(), JSTaggedValue::Undefined()); 130 131 std::string myValue("myvalue"); 132 for (uint32_t i = 1; i <= NODE_NUMBERS; i++) { 133 std::string ivalue = myValue + std::to_string(i); 134 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 135 JSTaggedValue result = JSAPIStack::Push(thread, toor, value); 136 EXPECT_EQ(result, value.GetTaggedValue()); 137 EXPECT_EQ(toor->Peek(), value.GetTaggedValue()); 138 } 139 140 for (uint32_t i = NODE_NUMBERS; i >= 1; i--) { 141 std::string ivalue = myValue + std::to_string(i); 142 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 143 JSTaggedValue gValue = toor->Pop(); 144 EXPECT_EQ(gValue, value.GetTaggedValue()); 145 } 146 147 toor->Dump(); 148 } 149 HWTEST_F_L0(JSAPIStackTest,Empty)150 HWTEST_F_L0(JSAPIStackTest, Empty) 151 { 152 constexpr uint32_t NODE_NUMBERS = 9; 153 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 154 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 155 156 JSHandle<JSAPIStack> toor(thread, CreateStack()); 157 158 std::string myValue("myvalue"); 159 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 160 std::string ivalue = myValue + std::to_string(i); 161 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 162 JSTaggedValue result = JSAPIStack::Push(thread, toor, value); 163 EXPECT_EQ(result, value.GetTaggedValue()); 164 EXPECT_EQ(toor->Peek(), value.GetTaggedValue()); 165 EXPECT_EQ(toor->Empty(), false); 166 } 167 168 int num = 8; 169 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 170 std::string ivalue = myValue + std::to_string(i); 171 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 172 toor->Pop(); 173 if (num == -1) { 174 EXPECT_EQ(toor->Empty(), true); 175 } 176 } 177 178 toor->Dump(); 179 } 180 HWTEST_F_L0(JSAPIStackTest,Search)181 HWTEST_F_L0(JSAPIStackTest, Search) 182 { 183 constexpr uint32_t NODE_NUMBERS = 9; 184 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 185 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 186 187 JSHandle<JSAPIStack> toor(thread, CreateStack()); 188 189 std::string myValue("myvalue"); 190 for (uint32_t i = 0; i < NODE_NUMBERS; i++) { 191 std::string ivalue = myValue + std::to_string(i); 192 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 193 JSTaggedValue result = JSAPIStack::Push(thread, toor, value); 194 EXPECT_EQ(result, value.GetTaggedValue()); 195 EXPECT_EQ(toor->Search(value), static_cast<int>(i)); 196 } 197 value.Update(factory->NewFromStdString(myValue).GetTaggedValue()); 198 EXPECT_EQ(toor->Search(value), -1); 199 200 toor->Dump(); 201 } 202 HWTEST_F_L0(JSAPIStackTest,GetOwnProperty)203 HWTEST_F_L0(JSAPIStackTest, GetOwnProperty) 204 { 205 constexpr uint32_t DEFAULT_LENGTH = 8; 206 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 207 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 208 JSHandle<JSAPIStack> toor(thread, CreateStack()); 209 210 std::string stackvalue("stackvalue"); 211 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) { 212 std::string ivalue = stackvalue + std::to_string(i); 213 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); 214 JSAPIStack::Push(thread, toor, value); 215 } 216 // test GetOwnProperty 217 int testInt = 1; 218 JSHandle<JSTaggedValue> stackKey1(thread, JSTaggedValue(testInt)); 219 EXPECT_TRUE(JSAPIStack::GetOwnProperty(thread, toor, stackKey1)); 220 testInt = 20; 221 JSHandle<JSTaggedValue> stackKey2(thread, JSTaggedValue(testInt)); 222 EXPECT_FALSE(JSAPIStack::GetOwnProperty(thread, toor, stackKey2)); 223 EXPECT_EXCEPTION(); 224 225 // test GetOwnProperty exception 226 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined()); 227 EXPECT_FALSE(JSAPIStack::GetOwnProperty(thread, toor, undefined)); 228 EXPECT_EXCEPTION(); 229 } 230 231 /** 232 * @tc.name: GetProperty 233 * @tc.desc: 234 * @tc.type: FUNC 235 * @tc.require: 236 */ HWTEST_F_L0(JSAPIStackTest,GetProperty)237 HWTEST_F_L0(JSAPIStackTest, GetProperty) 238 { 239 JSHandle<JSAPIStack> toor(thread, CreateStack()); 240 uint32_t elementsNums = 8; 241 for (uint32_t i = 0; i < elementsNums; i++) { 242 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i)); 243 JSAPIStack::Push(thread, toor, value); 244 } 245 for (uint32_t i = 0; i < elementsNums; i++) { 246 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i)); 247 OperationResult getPropertyRes = JSAPIStack::GetProperty(thread, toor, key); 248 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i)); 249 } 250 251 // test GetProperty Exception 252 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1)); 253 OperationResult getPropertyRes = JSAPIStack::GetProperty(thread, toor, key); 254 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue::Exception()); 255 EXPECT_EXCEPTION(); 256 257 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums)); 258 OperationResult getPropertyRes1 = JSAPIStack::GetProperty(thread, toor, key1); 259 EXPECT_EQ(getPropertyRes1.GetValue().GetTaggedValue(), JSTaggedValue::Exception()); 260 EXPECT_EXCEPTION(); 261 } 262 263 /** 264 * @tc.name: SetProperty 265 * @tc.desc: 266 * @tc.type: FUNC 267 * @tc.require: 268 */ HWTEST_F_L0(JSAPIStackTest,SetProperty)269 HWTEST_F_L0(JSAPIStackTest, SetProperty) 270 { 271 JSHandle<JSAPIStack> toor(thread, CreateStack()); 272 uint32_t elementsNums = 8; 273 for (uint32_t i = 0; i < elementsNums; i++) { 274 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i)); 275 JSAPIStack::Push(thread, toor, value); 276 } 277 for (uint32_t i = 0; i < elementsNums; i++) { 278 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i)); 279 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double 280 bool setPropertyRes = JSAPIStack::SetProperty(thread, toor, key, value); 281 EXPECT_EQ(setPropertyRes, true); 282 } 283 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1)); 284 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1)); 285 EXPECT_FALSE(JSAPIStack::SetProperty(thread, toor, key, value)); 286 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums)); 287 EXPECT_FALSE(JSAPIStack::SetProperty(thread, toor, key1, value)); 288 } 289 290 /** 291 * @tc.name: Has 292 * @tc.desc: 293 * @tc.type: FUNC 294 * @tc.require: 295 */ HWTEST_F_L0(JSAPIStackTest,Has)296 HWTEST_F_L0(JSAPIStackTest, Has) 297 { 298 JSHandle<JSAPIStack> toor(thread, CreateStack()); 299 300 // test Has empty 301 EXPECT_FALSE(toor->Has(JSTaggedValue(0))); 302 303 uint32_t elementsNums = 8; 304 for (uint32_t i = 0; i < elementsNums; i++) { 305 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i)); 306 JSAPIStack::Push(thread, toor, value); 307 } 308 for (uint32_t i = 0; i < elementsNums; i++) { 309 EXPECT_TRUE(toor->Has(JSTaggedValue(i))); 310 } 311 EXPECT_FALSE(toor->Has(JSTaggedValue(elementsNums))); 312 } 313 314 /** 315 * @tc.name: OwnKeys 316 * @tc.desc: 317 * @tc.type: FUNC 318 * @tc.require: 319 */ HWTEST_F_L0(JSAPIStackTest,OwnKeys)320 HWTEST_F_L0(JSAPIStackTest, OwnKeys) 321 { 322 JSHandle<JSAPIStack> toor(thread, CreateStack()); 323 uint32_t elementsNums = 8; 324 for (uint32_t i = 0; i < elementsNums; i++) { 325 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i)); 326 JSAPIStack::Push(thread, toor, value); 327 } 328 JSHandle<TaggedArray> keyArray = JSAPIStack::OwnKeys(thread, toor); 329 EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray()); 330 EXPECT_TRUE(keyArray->GetLength() == elementsNums); 331 for (uint32_t i = 0; i < elementsNums; i++) { 332 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))), 333 EcmaString::Cast(keyArray->Get(i).GetTaggedObject()))); 334 } 335 } 336 } // namespace panda::test 337