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/js_api/js_api_deque_iterator.h"
18 #include "ecmascript/js_api/js_api_deque.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/tests/ecma_test_common.h"
21
22 using namespace panda;
23 using namespace panda::ecmascript;
24
25 namespace panda::test {
26 class JSAPIDequeIteratorTest : public BaseTestWithScope<false> {
27 protected:
CreateJSApiDeque()28 JSAPIDeque *CreateJSApiDeque()
29 {
30 return EcmaContainerCommon::CreateJSApiDeque(thread);
31 }
32 };
33
34 /**
35 * @tc.name: Next
36 * @tc.desc: Create an iterator of JSAPIDeque,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(JSAPIDequeIteratorTest,Next)41 HWTEST_F_L0(JSAPIDequeIteratorTest, Next)
42 {
43 constexpr uint32_t DEFAULT_LENGTH = 8;
44 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
45 JSHandle<JSAPIDeque> jsDeque(thread, CreateJSApiDeque());
46 EXPECT_TRUE(*jsDeque != nullptr);
47 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
48 JSHandle<JSTaggedValue> valueStr = thread->GlobalConstants()->GetHandledValueString();
49 // insert value
50 std::string dequeValue("keyvalue");
51 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
52 std::string ivalue = dequeValue + std::to_string(i);
53 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
54 JSAPIDeque::InsertFront(thread, jsDeque, value);
55 }
56 JSHandle<JSAPIDequeIterator> dequeIterator = factory->NewJSAPIDequeIterator(jsDeque);
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(dequeIterator.GetTaggedValue());
61
62 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
63 JSTaggedValue result = JSAPIDequeIterator::Next(ecmaRuntimeCallInfo);
64 TestHelper::TearDownFrame(thread, prev);
65
66 JSHandle<JSObject> resultObj(thread, result);
67 if (i <= DEFAULT_LENGTH - 1U) {
68 EXPECT_EQ(dequeIterator->GetNextIndex(), i);
69 EXPECT_TRUE(JSObject::GetProperty(thread, resultObj, valueStr).GetValue()->IsString());
70 }
71 else {
72 EXPECT_TRUE(dequeIterator->GetIteratedDeque().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(JSAPIDequeIteratorTest,SpecialReturnOfNext)84 HWTEST_F_L0(JSAPIDequeIteratorTest, SpecialReturnOfNext)
85 {
86 JSHandle<JSAPIDeque> jsDeque(thread, CreateJSApiDeque());
87 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
88 JSHandle<JSAPIDequeIterator> dequeIterator = factory->NewJSAPIDequeIterator(jsDeque);
89 dequeIterator->SetIteratedDeque(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 = JSAPIDequeIterator::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(dequeIterator.GetTaggedValue());
109
110 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
111 JSTaggedValue result = JSAPIDequeIterator::Next(ecmaRuntimeCallInfo);
112 TestHelper::TearDownFrame(thread, prev);
113 EXPECT_EQ(result, thread->GlobalConstants()->GetUndefinedIterResult());
114 }
115 }
116
117 /**
118 * @tc.name: SetIteratedDeque
119 * @tc.desc: Call the "SetIteratedDeque" function, check whether the result returned through "GetIteratedDeque"
120 * function from the JSAPIDequeIterator is within expectations.
121 * @tc.type: FUNC
122 * @tc.require:
123 */
HWTEST_F_L0(JSAPIDequeIteratorTest,SetIteratedDeque)124 HWTEST_F_L0(JSAPIDequeIteratorTest, SetIteratedDeque)
125 {
126 constexpr uint32_t DEFAULT_LENGTH = 8;
127 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
128 JSHandle<JSAPIDeque> jsDeque1(thread, CreateJSApiDeque());
129 JSHandle<JSAPIDeque> jsDeque2(thread, CreateJSApiDeque());
130 EXPECT_TRUE(*jsDeque1 != nullptr);
131 EXPECT_TRUE(*jsDeque2 != nullptr);
132 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
133 // insert value
134 std::string dequeValue("keyvalue");
135 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
136 std::string ivalue = dequeValue + std::to_string(i);
137 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
138 JSAPIDeque::InsertFront(thread, jsDeque1, value);
139 }
140
141 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
142 std::string ivalue = dequeValue + std::to_string(i + 1U);
143 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
144 JSAPIDeque::InsertFront(thread, jsDeque2, value);
145 }
146 JSHandle<JSAPIDequeIterator> dequeIterator = factory->NewJSAPIDequeIterator(jsDeque1);
147 EXPECT_EQ(dequeIterator->GetIteratedDeque(), jsDeque1.GetTaggedValue());
148
149 dequeIterator->SetIteratedDeque(thread, jsDeque2.GetTaggedValue());
150 EXPECT_EQ(dequeIterator->GetIteratedDeque(), jsDeque2.GetTaggedValue());
151 }
152
153 /**
154 * @tc.name: SetNextIndex
155 * @tc.desc: Call the "SetNextIndex" function, check whether the result returned through "GetNextIndex"
156 * function from the JSAPIDequeIterator is within expectations.
157 * @tc.type: FUNC
158 * @tc.require:
159 */
HWTEST_F_L0(JSAPIDequeIteratorTest,SetNextIndex)160 HWTEST_F_L0(JSAPIDequeIteratorTest, SetNextIndex)
161 {
162 constexpr uint32_t DEFAULT_LENGTH = 8;
163 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
164 JSHandle<JSAPIDeque> jsDeque(thread, CreateJSApiDeque());
165 EXPECT_TRUE(*jsDeque != nullptr);
166 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
167 // insert value
168 std::string dequeValue("keyvalue");
169 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
170 std::string ivalue = dequeValue + std::to_string(i);
171 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
172 JSAPIDeque::InsertFront(thread, jsDeque, value);
173 }
174 JSHandle<JSAPIDequeIterator> dequeIterator = factory->NewJSAPIDequeIterator(jsDeque);
175 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
176 dequeIterator->SetNextIndex(i);
177 EXPECT_EQ(dequeIterator->GetNextIndex(), i);
178 }
179 }
180 } // namespace panda::test
181