• 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/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