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_deque.h"
21 #include "ecmascript/js_api/js_api_deque_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 using namespace panda::ecmascript;
32 using namespace panda::ecmascript::containers;
33
34 namespace panda::test {
35 class JSAPIDequeTest : public testing::Test {
36 public:
SetUpTestCase()37 static void SetUpTestCase()
38 {
39 GTEST_LOG_(INFO) << "SetUpTestCase";
40 }
41
TearDownTestCase()42 static void TearDownTestCase()
43 {
44 GTEST_LOG_(INFO) << "TearDownCase";
45 }
46
SetUp()47 void SetUp() override
48 {
49 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
50 }
51
TearDown()52 void TearDown() override
53 {
54 TestHelper::DestroyEcmaVMWithScope(instance, scope);
55 }
56
57 EcmaVM *instance {nullptr};
58 ecmascript::EcmaHandleScope *scope {nullptr};
59 JSThread *thread {nullptr};
60
61 protected:
CreateDeque()62 JSAPIDeque *CreateDeque()
63 {
64 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
65 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
66
67 JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
68 JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
69 JSHandle<JSTaggedValue> value =
70 JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
71
72 auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
73 objCallInfo->SetFunction(JSTaggedValue::Undefined());
74 objCallInfo->SetThis(value.GetTaggedValue());
75 objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(containers::ContainerTag::Deque)));
76
77 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
78 JSTaggedValue result = containers::ContainersPrivate::Load(objCallInfo);
79 TestHelper::TearDownFrame(thread, prev);
80
81 JSHandle<JSTaggedValue> constructor(thread, result);
82 JSHandle<JSAPIDeque> deque(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
83 JSHandle<TaggedArray> newElements = factory->NewTaggedArray(JSAPIDeque::DEFAULT_CAPACITY_LENGTH);
84 deque->SetElements(thread, newElements);
85 return *deque;
86 }
87 };
88
HWTEST_F_L0(JSAPIDequeTest,dequeCreate)89 HWTEST_F_L0(JSAPIDequeTest, dequeCreate)
90 {
91 JSAPIDeque *deque = CreateDeque();
92 EXPECT_TRUE(deque != nullptr);
93 }
94
HWTEST_F_L0(JSAPIDequeTest,InsertFrontAndGetFront)95 HWTEST_F_L0(JSAPIDequeTest, InsertFrontAndGetFront)
96 {
97 constexpr uint32_t NODE_NUMBERS = 9;
98 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
99 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
100
101 JSHandle<JSAPIDeque> toor(thread, CreateDeque());
102
103 // test GetFront of empty deque
104 EXPECT_EQ(toor->GetFront(), JSTaggedValue::Undefined());
105
106 std::string myValue("myvalue");
107 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
108 std::string ivalue = myValue + std::to_string(i);
109 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
110 JSAPIDeque::InsertFront(thread, toor, value);
111 EXPECT_EQ(toor->GetFront(), value.GetTaggedValue());
112 }
113
114 toor->Dump();
115 }
116
HWTEST_F_L0(JSAPIDequeTest,InsertEndAndGetTail)117 HWTEST_F_L0(JSAPIDequeTest, InsertEndAndGetTail)
118 {
119 constexpr uint32_t NODE_NUMBERS = 9;
120 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
121 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
122
123 JSHandle<JSAPIDeque> toor(thread, CreateDeque());
124
125 // test GetTail of empty deque
126 EXPECT_EQ(toor->GetTail(), JSTaggedValue::Undefined());
127
128 std::string myValue("myvalue");
129 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
130 std::string ivalue = myValue + std::to_string(i);
131 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
132 JSAPIDeque::InsertEnd(thread, toor, value);
133 EXPECT_EQ(toor->GetTail(), value.GetTaggedValue());
134 }
135
136 toor->Dump();
137 }
138
HWTEST_F_L0(JSAPIDequeTest,PopFirst)139 HWTEST_F_L0(JSAPIDequeTest, PopFirst)
140 {
141 constexpr uint32_t NODE_NUMBERS = 9;
142 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
143 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
144
145 JSHandle<JSAPIDeque> toor(thread, CreateDeque());
146
147 // test PopFirst of empty deque
148 EXPECT_EQ(toor->PopFirst(), JSTaggedValue::Undefined());
149
150 std::string myValue("myvalue");
151 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
152 std::string ivalue = myValue + std::to_string(i);
153 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
154 JSAPIDeque::InsertFront(thread, toor, value);
155 EXPECT_EQ(toor->PopFirst(), value.GetTaggedValue());
156 }
157
158 toor->Dump();
159 }
160
HWTEST_F_L0(JSAPIDequeTest,PopLast)161 HWTEST_F_L0(JSAPIDequeTest, PopLast)
162 {
163 constexpr uint32_t NODE_NUMBERS = 9;
164 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
165 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
166
167 JSHandle<JSAPIDeque> toor(thread, CreateDeque());
168
169 // test PopLast of empty deque
170 EXPECT_EQ(toor->PopLast(), JSTaggedValue::Undefined());
171
172 std::string myValue("myvalue");
173 for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
174 std::string ivalue = myValue + std::to_string(i);
175 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
176 JSAPIDeque::InsertEnd(thread, toor, value);
177 EXPECT_EQ(toor->PopLast(), value.GetTaggedValue());
178 }
179
180 toor->Dump();
181 }
182
HWTEST_F_L0(JSAPIDequeTest,GetOwnProperty)183 HWTEST_F_L0(JSAPIDequeTest, GetOwnProperty)
184 {
185 constexpr uint32_t DEFAULT_LENGTH = 8;
186 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
187 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
188 JSHandle<JSAPIDeque> toor(thread, CreateDeque());
189
190 std::string dequeValue("dequevalue");
191 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
192 std::string ivalue = dequeValue + std::to_string(i);
193 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
194 JSAPIDeque::InsertFront(thread, toor, value);
195 JSAPIDeque::InsertEnd(thread, toor, value);
196 }
197 // test GetOwnProperty
198 int testInt = 1;
199 JSHandle<JSTaggedValue> dequeKey1(thread, JSTaggedValue(testInt));
200 EXPECT_TRUE(JSAPIDeque::GetOwnProperty(thread, toor, dequeKey1));
201 testInt = 20;
202 JSHandle<JSTaggedValue> dequeKey2(thread, JSTaggedValue(testInt));
203 EXPECT_FALSE(JSAPIDeque::GetOwnProperty(thread, toor, dequeKey2));
204 EXPECT_EXCEPTION();
205
206 // test GetOwnProperty exception
207 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
208 EXPECT_FALSE(JSAPIDeque::GetOwnProperty(thread, toor, undefined));
209 EXPECT_EXCEPTION();
210 }
211
212 /**
213 * @tc.name: GetProperty
214 * @tc.desc:
215 * @tc.type: FUNC
216 * @tc.require:
217 */
HWTEST_F_L0(JSAPIDequeTest,GetProperty)218 HWTEST_F_L0(JSAPIDequeTest, GetProperty)
219 {
220 JSHandle<JSAPIDeque> toor(thread, CreateDeque());
221 uint32_t elementsNums = 8;
222 for (uint32_t i = 0; i < elementsNums; i++) {
223 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
224 JSAPIDeque::InsertEnd(thread, toor, value);
225 }
226 for (uint32_t i = 0; i < elementsNums; i++) {
227 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
228 OperationResult getPropertyRes = JSAPIDeque::GetProperty(thread, toor, key);
229 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
230 }
231 }
232
233 /**
234 * @tc.name: SetProperty
235 * @tc.desc:
236 * @tc.type: FUNC
237 * @tc.require:
238 */
HWTEST_F_L0(JSAPIDequeTest,SetProperty)239 HWTEST_F_L0(JSAPIDequeTest, SetProperty)
240 {
241 JSHandle<JSAPIDeque> toor(thread, CreateDeque());
242 uint32_t elementsNums = 8;
243 for (uint32_t i = 0; i < elementsNums; i++) {
244 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
245 JSAPIDeque::InsertFront(thread, toor, value);
246 JSAPIDeque::InsertEnd(thread, toor, value);
247 }
248 for (uint32_t i = 0; i < elementsNums; i++) {
249 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
250 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
251 bool setPropertyRes = JSAPIDeque::SetProperty(thread, toor, key, value);
252 EXPECT_EQ(setPropertyRes, true);
253 }
254 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
255 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
256 EXPECT_FALSE(JSAPIDeque::SetProperty(thread, toor, key, value));
257 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums * 2));
258 EXPECT_FALSE(JSAPIDeque::SetProperty(thread, toor, key1, value));
259 }
260
261 /**
262 * @tc.name: OwnKeys
263 * @tc.desc:
264 * @tc.type: FUNC
265 * @tc.require:
266 */
HWTEST_F_L0(JSAPIDequeTest,OwnKeys)267 HWTEST_F_L0(JSAPIDequeTest, OwnKeys)
268 {
269 JSHandle<JSAPIDeque> toor(thread, CreateDeque());
270 uint32_t elementsNums = 8;
271 for (uint32_t i = 0; i < elementsNums; i++) {
272 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
273 JSAPIDeque::InsertEnd(thread, toor, value);
274 }
275
276 // test OwnKeys
277 JSHandle<TaggedArray> keyArray = JSAPIDeque::OwnKeys(thread, toor);
278 EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
279 EXPECT_TRUE(keyArray->GetLength() == elementsNums);
280 for (uint32_t i = 0; i < elementsNums; i++) {
281 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
282 EcmaString::Cast(keyArray->Get(i).GetTaggedObject())));
283 }
284 }
285 } // namespace panda::test
286