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_stack_iterator.h"
17 #include "ecmascript/containers/containers_private.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_api/js_api_stack.h"
20 #include "ecmascript/tests/ecma_test_common.h"
21
22 using namespace panda::ecmascript;
23 using namespace panda::ecmascript::containers;
24
25 namespace panda::test {
26 class JSAPIStackIteratorTest : public BaseTestWithScope<false> {
27 protected:
CreateJSApiStack(JSThread * thread)28 static JSHandle<JSAPIStack> CreateJSApiStack(JSThread *thread)
29 {
30 return EcmaContainerCommon::CreateJSApiStack(thread);
31 }
32 };
33
34 /**
35 * @tc.name: Next
36 * @tc.desc: Create an iterator of JSAPIStack,and then loop through the elements of the iterator to check whether
37 * the elements are consistent through Next function.
38 * @tc.type: FUNC
39 * @tc.require:
40 */
HWTEST_F_L0(JSAPIStackIteratorTest,Next)41 HWTEST_F_L0(JSAPIStackIteratorTest, Next)
42 {
43 constexpr uint32_t DEFAULT_LENGTH = 9;
44 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
45 JSHandle<JSAPIStack> jsStack = CreateJSApiStack(thread);
46 EXPECT_TRUE(*jsStack != nullptr);
47 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
48 JSHandle<JSTaggedValue> valueStr = thread->GlobalConstants()->GetHandledValueString();
49 // insert value
50 std::string stackValue("keyvalue");
51 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
52 std::string ivalue = stackValue + std::to_string(i);
53 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
54 JSAPIStack::Push(thread, jsStack, value);
55 }
56 JSHandle<JSAPIStackIterator> stackIterator = factory->NewJSAPIStackIterator(jsStack);
57 for (uint32_t i = 0; i <= DEFAULT_LENGTH; i++) {
58 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
59 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
60 ecmaRuntimeCallInfo->SetThis(stackIterator.GetTaggedValue());
61
62 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
63 JSTaggedValue result = JSAPIStackIterator::Next(ecmaRuntimeCallInfo);
64 TestHelper::TearDownFrame(thread, prev);
65
66 JSHandle<JSObject> resultObj(thread, result);
67 if (i <= DEFAULT_LENGTH - 1U) {
68 EXPECT_EQ(stackIterator->GetNextIndex(), (i + 1U));
69 EXPECT_TRUE(JSObject::GetProperty(thread, resultObj, valueStr).GetValue()->IsString());
70 }
71 else {
72 EXPECT_TRUE(stackIterator->GetIteratedStack(thread).IsUndefined());
73 EXPECT_TRUE(JSObject::GetProperty(thread, resultObj, valueStr).GetValue()->IsUndefined());
74 }
75 }
76 }
77
78 /**
79 * @tc.name: Next
80 * @tc.desc: test special return of Next, including throw exception and return undefined
81 * @tc.type: FUNC
82 * @tc.require:
83 */
HWTEST_F_L0(JSAPIStackIteratorTest,SpecialReturnOfNext)84 HWTEST_F_L0(JSAPIStackIteratorTest, SpecialReturnOfNext)
85 {
86 JSHandle<JSAPIStack> jsStack = CreateJSApiStack(thread);
87 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
88 JSHandle<JSAPIStackIterator> stackIterator = factory->NewJSAPIStackIterator(jsStack);
89 stackIterator->SetIteratedStack(thread, JSTaggedValue::Undefined());
90
91 // test Next exception
92 {
93 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
94 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
95 ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
96
97 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
98 JSTaggedValue result = JSAPIStackIterator::Next(ecmaRuntimeCallInfo);
99 TestHelper::TearDownFrame(thread, prev);
100 EXPECT_EQ(result, JSTaggedValue::Exception());
101 EXPECT_EXCEPTION();
102 }
103
104 // test Next return undefined
105 {
106 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
107 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
108 ecmaRuntimeCallInfo->SetThis(stackIterator.GetTaggedValue());
109
110 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
111 JSTaggedValue result = JSAPIStackIterator::Next(ecmaRuntimeCallInfo);
112 TestHelper::TearDownFrame(thread, prev);
113 EXPECT_EQ(result, thread->GetEcmaVM()->GetGlobalEnv()->GetUndefinedIteratorResult().GetTaggedValue());
114 }
115 }
116
117 /**
118 * @tc.name: SetIteratedStack
119 * @tc.desc: Call the "SetIteratedStack" function, check whether the result returned through "GetIteratedStack"
120 * function from the JSAPIStackIterator is within expectations.
121 * @tc.type: FUNC
122 * @tc.require:
123 */
HWTEST_F_L0(JSAPIStackIteratorTest,SetIteratedStack)124 HWTEST_F_L0(JSAPIStackIteratorTest, SetIteratedStack)
125 {
126 constexpr uint32_t DEFAULT_LENGTH = 9;
127 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
128 JSHandle<JSAPIStack> jsStack1 = CreateJSApiStack(thread);
129 JSHandle<JSAPIStack> jsStack2 = CreateJSApiStack(thread);
130 EXPECT_TRUE(*jsStack1 != nullptr);
131 EXPECT_TRUE(*jsStack2 != nullptr);
132 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
133 // insert value
134 std::string stackValue("keyvalue");
135 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
136 std::string ivalue = stackValue + std::to_string(i);
137 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
138 JSAPIStack::Push(thread, jsStack1, value);
139 }
140
141 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
142 std::string ivalue = stackValue + std::to_string(i + 2U);
143 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
144 JSAPIStack::Push(thread, jsStack2, value);
145 }
146 JSHandle<JSAPIStackIterator> stackIterator = factory->NewJSAPIStackIterator(jsStack1);
147 EXPECT_EQ(stackIterator->GetIteratedStack(thread), jsStack1.GetTaggedValue());
148
149 stackIterator->SetIteratedStack(thread, jsStack2.GetTaggedValue());
150 JSHandle<JSAPIStack> jsAPIStackTo(thread,
151 JSAPIStack::Cast(stackIterator->GetIteratedStack(thread).GetTaggedObject()));
152 EXPECT_EQ(jsAPIStackTo->GetSize(), static_cast<int>(DEFAULT_LENGTH - 1U));
153
154 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
155 std::string ivalue = stackValue + std::to_string(i + 2U);
156 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
157 EXPECT_EQ(jsAPIStackTo->Search(thread, value), static_cast<int>(i));
158 }
159 }
160
161 /**
162 * @tc.name: SetNextIndex
163 * @tc.desc: Call the "SetNextIndex" function, check whether the result returned through "GetNextIndex"
164 * function from the JSAPIStackIterator is within expectations.
165 * @tc.type: FUNC
166 * @tc.require:
167 */
HWTEST_F_L0(JSAPIStackIteratorTest,SetNextIndex)168 HWTEST_F_L0(JSAPIStackIteratorTest, SetNextIndex)
169 {
170 constexpr uint32_t DEFAULT_LENGTH = 9;
171 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
172 JSHandle<JSAPIStack> jsStack = CreateJSApiStack(thread);
173 EXPECT_TRUE(*jsStack != nullptr);
174 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
175 // insert value
176 std::string stackValue("keyvalue");
177 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
178 std::string ivalue = stackValue + std::to_string(i);
179 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
180 JSAPIStack::Push(thread, jsStack, value);
181 }
182 JSHandle<JSAPIStackIterator> stackIterator = factory->NewJSAPIStackIterator(jsStack);
183 EXPECT_EQ(stackIterator->GetNextIndex(), 0U);
184
185 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
186 stackIterator->SetNextIndex(i);
187 EXPECT_EQ(stackIterator->GetNextIndex(), i);
188 }
189 }
190 } // namespace panda::ecmascript
191