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