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 ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
168 EcmaString::Cast(arrayKey->Get(i).GetTaggedObject())));
169 }
170 }
171
HWTEST_F_L0(JSAPIQueueTest,GetNextPosition)172 HWTEST_F_L0(JSAPIQueueTest, GetNextPosition)
173 {
174 constexpr uint32_t DEFAULT_LENGTH = 8;
175 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
176 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
177 JSHandle<JSAPIQueue> jsQueue = CreateQueue();
178
179 std::string queueValue("queuevalue");
180 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
181 std::string ivalue = queueValue + std::to_string(i);
182 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
183 JSAPIQueue::Add(thread, jsQueue, value);
184 }
185 // test GetNextPosition
186 EXPECT_EQ(jsQueue->GetSize(), DEFAULT_LENGTH);
187 for (uint32_t i = 0; i < DEFAULT_LENGTH;) {
188 std::string ivalue = queueValue + std::to_string(i);
189 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
190 EXPECT_EQ(jsQueue->Get(thread, i), value.GetTaggedValue());
191 i = jsQueue->GetNextPosition(i);
192 }
193 }
194
HWTEST_F_L0(JSAPIQueueTest,GetOwnProperty)195 HWTEST_F_L0(JSAPIQueueTest, GetOwnProperty)
196 {
197 constexpr uint32_t DEFAULT_LENGTH = 8;
198 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
199 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
200 JSHandle<JSAPIQueue> jsQueue = CreateQueue();
201
202 std::string queueValue("queuevalue");
203 for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) {
204 std::string ivalue = queueValue + std::to_string(i);
205 value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
206 JSAPIQueue::Add(thread, jsQueue, value);
207 }
208 // test GetOwnProperty
209 int testInt = 1;
210 JSHandle<JSTaggedValue> queueKey1(thread, JSTaggedValue(testInt));
211 EXPECT_TRUE(JSAPIQueue::GetOwnProperty(thread, jsQueue, queueKey1));
212 testInt = 9;
213 JSHandle<JSTaggedValue> queueKey2(thread, JSTaggedValue(testInt));
214 EXPECT_FALSE(JSAPIQueue::GetOwnProperty(thread, jsQueue, queueKey2));
215 EXPECT_EXCEPTION();
216
217 // test GetOwnProperty exception
218 JSHandle<JSTaggedValue> undefined(thread, JSTaggedValue::Undefined());
219 EXPECT_FALSE(JSAPIQueue::GetOwnProperty(thread, jsQueue, undefined));
220 EXPECT_EXCEPTION();
221 }
222
223 /**
224 * @tc.name: GetProperty
225 * @tc.desc:
226 * @tc.type: FUNC
227 * @tc.require:
228 */
HWTEST_F_L0(JSAPIQueueTest,GetProperty)229 HWTEST_F_L0(JSAPIQueueTest, GetProperty)
230 {
231 JSHandle<JSAPIQueue> jsQueue = CreateQueue();
232 uint32_t elementsNums = 8;
233 for (uint32_t i = 0; i < elementsNums; i++) {
234 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
235 JSAPIQueue::Add(thread, jsQueue, value);
236 }
237 for (uint32_t i = 0; i < elementsNums; i++) {
238 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
239 OperationResult getPropertyRes = JSAPIQueue::GetProperty(thread, jsQueue, key);
240 EXPECT_EQ(getPropertyRes.GetValue().GetTaggedValue(), JSTaggedValue(i));
241 }
242 }
243
244 /**
245 * @tc.name: SetProperty
246 * @tc.desc:
247 * @tc.type: FUNC
248 * @tc.require:
249 */
HWTEST_F_L0(JSAPIQueueTest,SetProperty)250 HWTEST_F_L0(JSAPIQueueTest, SetProperty)
251 {
252 JSHandle<JSAPIQueue> jsQueue = CreateQueue();
253 uint32_t elementsNums = 8;
254 for (uint32_t i = 0; i < elementsNums; i++) {
255 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i));
256 JSAPIQueue::Add(thread, jsQueue, value);
257 }
258 for (uint32_t i = 0; i < elementsNums; i++) {
259 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(i));
260 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(i * 2)); // 2 : It means double
261 bool setPropertyRes = JSAPIQueue::SetProperty(thread, jsQueue, key, value);
262 EXPECT_EQ(setPropertyRes, true);
263 }
264 JSHandle<JSTaggedValue> key(thread, JSTaggedValue(-1));
265 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(-1));
266 EXPECT_FALSE(JSAPIQueue::SetProperty(thread, jsQueue, key, value));
267 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(elementsNums));
268 EXPECT_FALSE(JSAPIQueue::SetProperty(thread, jsQueue, key1, value));
269 }
270
271 /**
272 * @tc.name: GrowCapacity
273 * @tc.desc:
274 * @tc.type: FUNC
275 * @tc.require:
276 */
HWTEST_F_L0(JSAPIQueueTest,GrowCapacity)277 HWTEST_F_L0(JSAPIQueueTest, GrowCapacity)
278 {
279 JSHandle<JSAPIQueue> jsQueue = CreateQueue(0);
280 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(0));
281 JSHandle<TaggedArray> element(thread, jsQueue->GetElements());
282 EXPECT_EQ(element->GetLength(), 0U);
283 JSAPIQueue::Add(thread, jsQueue, value);
284 JSHandle<TaggedArray> newElement(thread, jsQueue->GetElements());
285 EXPECT_EQ(newElement->GetLength(), static_cast<uint32_t>(JSAPIQueue::DEFAULT_CAPACITY_LENGTH));
286 }
287 } // namespace panda::test