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/ecma_test_common.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 BaseTestWithScope<false> {
38 protected:
CreateStack()39 JSAPIStack *CreateStack()
40 {
41 return *EcmaContainerCommon::CreateJSApiStack(thread);
42 }
43
SearchAndEmptyCommon(JSMutableHandle<JSTaggedValue> & value,std::string & myValue,uint32_t len,bool search=false)44 JSHandle<JSAPIStack> SearchAndEmptyCommon(JSMutableHandle<JSTaggedValue>& value, std::string& myValue,
45 uint32_t len, bool search = false)
46 {
47 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
48
49 JSHandle<JSAPIStack> toor(thread, CreateStack());
50 for (uint32_t i = 0; i < len; i++) {
51 std::string ivalue = myValue + std::to_string(i);
52 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
53 JSTaggedValue result = JSAPIStack::Push(thread, toor, value);
54 EXPECT_EQ(result, value.GetTaggedValue());
55 if (search) {
56 EXPECT_EQ(toor->Search(thread, value), static_cast<int>(i));
57 } else {
58 EXPECT_EQ(toor->Peek(thread), value.GetTaggedValue());
59 EXPECT_EQ(toor->Empty(), false);
60 }
61 }
62 return toor;
63 }
64 };
65
HWTEST_F_L0(JSAPIStackTest,stackCreate)66 HWTEST_F_L0(JSAPIStackTest, stackCreate)
67 {
68 JSAPIStack *stack = CreateStack();
69 EXPECT_TRUE(stack != nullptr);
70 }
71
HWTEST_F_L0(JSAPIStackTest,PushAndPeek)72 HWTEST_F_L0(JSAPIStackTest, PushAndPeek)
73 {
74 constexpr uint32_t NODE_NUMBERS = 9;
75 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
76 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
77
78 JSHandle<JSAPIStack> toor(thread, CreateStack());
79
80 // test Peek empty
81 EXPECT_EQ(toor->Peek(thread), JSTaggedValue::Undefined());
82
83 std::string myValue("myvalue");
84 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
85 std::string ivalue = myValue + std::to_string(i);
86 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
87 JSTaggedValue result = JSAPIStack::Push(thread, toor, value);
88 EXPECT_EQ(result, value.GetTaggedValue());
89 EXPECT_EQ(toor->Peek(thread), value.GetTaggedValue());
90 }
91 EXPECT_EQ(static_cast<uint32_t>(toor->GetTop() + 1), NODE_NUMBERS);
92
93 toor->Dump(thread);
94 }
95
HWTEST_F_L0(JSAPIStackTest,Pop)96 HWTEST_F_L0(JSAPIStackTest, Pop)
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 Pop empty
105 EXPECT_EQ(toor->Pop(thread), JSTaggedValue::Undefined());
106
107 std::string myValue("myvalue");
108 for (uint32_t i = 1; 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(thread), value.GetTaggedValue());
114 }
115
116 for (uint32_t i = NODE_NUMBERS; i >= 1; i--) {
117 std::string ivalue = myValue + std::to_string(i);
118 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
119 JSTaggedValue gValue = toor->Pop(thread);
120 EXPECT_EQ(gValue, value.GetTaggedValue());
121 }
122
123 toor->Dump(thread);
124 }
125
HWTEST_F_L0(JSAPIStackTest,Empty)126 HWTEST_F_L0(JSAPIStackTest, Empty)
127 {
128 constexpr uint32_t NODE_NUMBERS = 9;
129 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
130 std::string myValue("myvalue");
131 auto toor = SearchAndEmptyCommon(value, myValue, NODE_NUMBERS);
132
133 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
134 int num = 8;
135 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
136 std::string ivalue = myValue + std::to_string(i);
137 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
138 toor->Pop(thread);
139 if (num == -1) {
140 EXPECT_EQ(toor->Empty(), true);
141 }
142 }
143
144 toor->Dump(thread);
145 }
146
HWTEST_F_L0(JSAPIStackTest,Search)147 HWTEST_F_L0(JSAPIStackTest, Search)
148 {
149 constexpr uint32_t NODE_NUMBERS = 9;
150 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
151 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
152 std::string myValue("myvalue");
153 auto toor = SearchAndEmptyCommon(value, myValue, NODE_NUMBERS, true);
154 value.Update(factory->NewFromStdString(myValue).GetTaggedValue());
155 EXPECT_EQ(toor->Search(thread, value), -1);
156
157 toor->Dump(thread);
158 }
159
HWTEST_F_L0(JSAPIStackTest,GetOwnProperty)160 HWTEST_F_L0(JSAPIStackTest, GetOwnProperty)
161 {
162 constexpr uint32_t DEFAULT_LENGTH = 8;
163 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
164 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
165 JSHandle<JSAPIStack> toor(thread, CreateStack());
166
167 std::string stackvalue("stackvalue");
168 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
169 std::string ivalue = stackvalue + std::to_string(i);
170 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
171 JSAPIStack::Push(thread, toor, value);
172 }
173 // test GetOwnProperty
174 int testInt = 1;
175 JSHandle<JSTaggedValue> stackKey1(thread, JSTaggedValue(testInt));
176 EXPECT_TRUE(JSAPIStack::GetOwnProperty(thread, toor, stackKey1));
177 testInt = 20;
178 JSHandle<JSTaggedValue> stackKey2(thread, JSTaggedValue(testInt));
179 EXPECT_FALSE(JSAPIStack::GetOwnProperty(thread, toor, stackKey2));
180 EXPECT_EXCEPTION();
181
182 // test GetOwnProperty exception
183 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
184 EXPECT_FALSE(JSAPIStack::GetOwnProperty(thread, toor, undefined));
185 EXPECT_EXCEPTION();
186 }
187
188 /**
189 * @tc.name: GetProperty
190 * @tc.desc:
191 * @tc.type: FUNC
192 * @tc.require:
193 */
HWTEST_F_L0(JSAPIStackTest,GetProperty)194 HWTEST_F_L0(JSAPIStackTest, GetProperty)
195 {
196 JSHandle<JSAPIStack> toor(thread, CreateStack());
197 uint32_t elementsNums = 8;
198 for (uint32_t i = 0; i < elementsNums; i++) {
199 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
200 JSAPIStack::Push(thread, toor, value);
201 }
202 for (uint32_t i = 0; i < elementsNums; i++) {
203 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
204 OperationResult getPropertyRes = JSAPIStack::GetProperty(thread, toor, key);
205 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
206 }
207
208 // test GetProperty Exception
209 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
210 OperationResult getPropertyRes = JSAPIStack::GetProperty(thread, toor, key);
211 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue::Exception());
212 EXPECT_EXCEPTION();
213
214 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
215 OperationResult getPropertyRes1 = JSAPIStack::GetProperty(thread, toor, key1);
216 EXPECT_EQ(getPropertyRes1.GetValue().GetTaggedValue(), JSTaggedValue::Exception());
217 EXPECT_EXCEPTION();
218 }
219
220 /**
221 * @tc.name: SetProperty
222 * @tc.desc:
223 * @tc.type: FUNC
224 * @tc.require:
225 */
HWTEST_F_L0(JSAPIStackTest,SetProperty)226 HWTEST_F_L0(JSAPIStackTest, SetProperty)
227 {
228 JSHandle<JSAPIStack> toor(thread, CreateStack());
229 uint32_t elementsNums = 8;
230 {
231 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
232 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
233 EXPECT_EQ(JSTaggedValue::Undefined(), // when length = -1, return Undefine() instead of assert error
234 toor->Set(thread, key->GetInt(), value.GetTaggedValue()));
235 }
236 for (uint32_t i = 0; i < elementsNums; i++) {
237 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
238 JSAPIStack::Push(thread, toor, value);
239 }
240 for (uint32_t i = 0; i < elementsNums; i++) {
241 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
242 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
243 bool setPropertyRes = JSAPIStack::SetProperty(thread, toor, key, value);
244 EXPECT_EQ(setPropertyRes, true);
245 }
246 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
247 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
248 EXPECT_FALSE(JSAPIStack::SetProperty(thread, toor, key, value));
249 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
250 EXPECT_FALSE(JSAPIStack::SetProperty(thread, toor, key1, value));
251 }
252
253 /**
254 * @tc.name: Has
255 * @tc.desc:
256 * @tc.type: FUNC
257 * @tc.require:
258 */
HWTEST_F_L0(JSAPIStackTest,Has)259 HWTEST_F_L0(JSAPIStackTest, Has)
260 {
261 JSHandle<JSAPIStack> toor(thread, CreateStack());
262
263 // test Has empty
264 EXPECT_FALSE(toor->Has(thread, JSTaggedValue(0)));
265
266 uint32_t elementsNums = 8;
267 for (uint32_t i = 0; i < elementsNums; i++) {
268 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
269 JSAPIStack::Push(thread, toor, value);
270 }
271 for (uint32_t i = 0; i < elementsNums; i++) {
272 EXPECT_TRUE(toor->Has(thread, JSTaggedValue(i)));
273 }
274 EXPECT_FALSE(toor->Has(thread, JSTaggedValue(elementsNums)));
275 }
276
277 /**
278 * @tc.name: OwnKeys
279 * @tc.desc:
280 * @tc.type: FUNC
281 * @tc.require:
282 */
HWTEST_F_L0(JSAPIStackTest,OwnKeys)283 HWTEST_F_L0(JSAPIStackTest, OwnKeys)
284 {
285 JSHandle<JSAPIStack> toor(thread, CreateStack());
286 uint32_t elementsNums = 8;
287 for (uint32_t i = 0; i < elementsNums; i++) {
288 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
289 JSAPIStack::Push(thread, toor, value);
290 }
291 JSHandle<TaggedArray> keyArray = JSAPIStack::OwnKeys(thread, toor);
292 EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
293 EXPECT_TRUE(keyArray->GetLength() == elementsNums);
294 for (uint32_t i = 0; i < elementsNums; i++) {
295 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread,
296 *(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
297 EcmaString::Cast(keyArray->Get(thread, i).GetTaggedObject())));
298 }
299 }
300 } // namespace panda::test
301