• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_deque.h"
17 #include "ecmascript/containers/containers_private.h"
18 #include "ecmascript/ecma_runtime_call_info.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_handle.h"
23 #include "ecmascript/js_tagged_value-inl.h"
24 #include "ecmascript/js_thread.h"
25 #include "ecmascript/object_factory.h"
26 #include "ecmascript/tests/test_helper.h"
27 #include "ecmascript/containers/tests/containers_test_helper.h"
28 
29 using namespace panda::ecmascript;
30 using namespace panda::ecmascript::containers;
31 
32 namespace panda::test {
33 class ContainersDequeTest : public testing::Test {
34 public:
SetUpTestCase()35     static void SetUpTestCase()
36     {
37         GTEST_LOG_(INFO) << "SetUpTestCase";
38     }
39 
TearDownTestCase()40     static void TearDownTestCase()
41     {
42         GTEST_LOG_(INFO) << "TearDownCase";
43     }
44 
SetUp()45     void SetUp() override
46     {
47         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
48     }
49 
TearDown()50     void TearDown() override
51     {
52         TestHelper::DestroyEcmaVMWithScope(instance, scope);
53     }
54 
55     EcmaVM *instance {nullptr};
56     EcmaHandleScope *scope {nullptr};
57     JSThread *thread {nullptr};
58 
59     class TestClass : public base::BuiltinsBase {
60     public:
TestForEachFunc(EcmaRuntimeCallInfo * argv)61         static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
62         {
63             JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
64             JSHandle<JSTaggedValue> key = GetCallArg(argv, 1);
65             JSHandle<JSTaggedValue> deque = GetCallArg(argv, 2); // 2 means the secode arg
66             if (!deque->IsUndefined()) {
67                 if (value->IsNumber()) {
68                     TaggedArray *elements = TaggedArray::Cast(JSAPIDeque::Cast(deque.GetTaggedValue().
69                                             GetTaggedObject())->GetElements().GetTaggedObject());
70                     JSTaggedValue result = elements->Get(key->GetInt());
71                     EXPECT_EQ(result, value.GetTaggedValue());
72                 }
73             }
74             return JSTaggedValue::True();
75         }
76     };
77 protected:
InitializeDequeConstructor()78     JSTaggedValue InitializeDequeConstructor()
79     {
80         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
81         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
82 
83         JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
84         JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
85         JSHandle<JSTaggedValue> value =
86             JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
87 
88         auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
89         objCallInfo->SetFunction(JSTaggedValue::Undefined());
90         objCallInfo->SetThis(value.GetTaggedValue());
91         objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::Deque)));
92         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
93         JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
94         TestHelper::TearDownFrame(thread, prev);
95 
96         return result;
97     }
98 
CreateJSAPIDeque(JSTaggedValue compare=JSTaggedValue::Undefined ())99     JSHandle<JSAPIDeque> CreateJSAPIDeque(JSTaggedValue compare = JSTaggedValue::Undefined())
100     {
101         JSHandle<JSTaggedValue> compareHandle(thread, compare);
102         JSHandle<JSFunction> newTarget(thread, InitializeDequeConstructor());
103         auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
104         objCallInfo->SetFunction(newTarget.GetTaggedValue());
105         objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
106         objCallInfo->SetThis(JSTaggedValue::Undefined());
107         objCallInfo->SetCallArg(0, compareHandle.GetTaggedValue());
108 
109         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
110         JSTaggedValue result = ContainersDeque::DequeConstructor(objCallInfo);
111         TestHelper::TearDownFrame(thread, prev);
112         JSHandle<JSAPIDeque> deque(thread, result);
113         return deque;
114     }
115 };
116 
HWTEST_F_L0(ContainersDequeTest,DequeConstructor)117 HWTEST_F_L0(ContainersDequeTest, DequeConstructor)
118 {
119     InitializeDequeConstructor();
120     JSHandle<JSFunction> newTarget(thread, InitializeDequeConstructor());
121 
122     auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
123     objCallInfo->SetFunction(newTarget.GetTaggedValue());
124     objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
125     objCallInfo->SetThis(JSTaggedValue::Undefined());
126 
127     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
128     JSTaggedValue result = ContainersDeque::DequeConstructor(objCallInfo);
129     TestHelper::TearDownFrame(thread, prev);
130 
131     ASSERT_TRUE(result.IsJSAPIDeque());
132     JSHandle<JSAPIDeque> deque(thread, result);
133     JSTaggedValue resultProto = JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(deque));
134     JSTaggedValue funcProto = newTarget->GetFunctionPrototype();
135     ASSERT_EQ(resultProto, funcProto);
136 
137     // test DequeConstructor exception
138     objCallInfo->SetNewTarget(JSTaggedValue::Undefined());
139     CONTAINERS_API_EXCEPTION_TEST(ContainersDeque, DequeConstructor, objCallInfo);
140 }
141 
HWTEST_F_L0(ContainersDequeTest,InsertFrontAndGetFirst)142 HWTEST_F_L0(ContainersDequeTest, InsertFrontAndGetFirst)
143 {
144     constexpr uint32_t NODE_NUMBERS = 8;
145     JSHandle<JSAPIDeque> deque = CreateJSAPIDeque();
146     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
147         auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
148         callInfo->SetFunction(JSTaggedValue::Undefined());
149         callInfo->SetThis(deque.GetTaggedValue());
150         callInfo->SetCallArg(0, JSTaggedValue(i));
151 
152         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
153         JSTaggedValue result = ContainersDeque::InsertFront(callInfo);
154         TestHelper::TearDownFrame(thread, prev);
155         EXPECT_EQ(result, JSTaggedValue::True());
156         EXPECT_EQ(ContainersDeque::GetFirst(callInfo), JSTaggedValue(i));
157     }
158 }
159 
HWTEST_F_L0(ContainersDequeTest,InsertEndAndGetLast)160 HWTEST_F_L0(ContainersDequeTest, InsertEndAndGetLast)
161 {
162     constexpr uint32_t NODE_NUMBERS = 8;
163     JSHandle<JSAPIDeque> deque = CreateJSAPIDeque();
164     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
165         auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
166         callInfo->SetFunction(JSTaggedValue::Undefined());
167         callInfo->SetThis(deque.GetTaggedValue());
168         callInfo->SetCallArg(0, JSTaggedValue(i));
169 
170         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
171         JSTaggedValue result = ContainersDeque::InsertEnd(callInfo);
172         TestHelper::TearDownFrame(thread, prev);
173         EXPECT_EQ(result, JSTaggedValue::True());
174         EXPECT_EQ(ContainersDeque::GetLast(callInfo), JSTaggedValue(i));
175     }
176 }
177 
HWTEST_F_L0(ContainersDequeTest,Has)178 HWTEST_F_L0(ContainersDequeTest, Has)
179 {
180     constexpr uint32_t NODE_NUMBERS = 8;
181     JSHandle<JSAPIDeque> deque = CreateJSAPIDeque();
182     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
183         auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
184         callInfo->SetFunction(JSTaggedValue::Undefined());
185         callInfo->SetThis(deque.GetTaggedValue());
186         callInfo->SetCallArg(0, JSTaggedValue(i));
187 
188         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
189         ContainersDeque::InsertEnd(callInfo);
190         TestHelper::TearDownFrame(thread, prev);
191     }
192 
193     int num = 7;
194     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
195         auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
196         callInfo->SetFunction(JSTaggedValue::Undefined());
197         callInfo->SetThis(deque.GetTaggedValue());
198         callInfo->SetCallArg(0, JSTaggedValue(i));
199 
200         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
201         JSTaggedValue result = ContainersDeque::Has(callInfo);
202         TestHelper::TearDownFrame(thread, prev);
203         EXPECT_EQ(result, JSTaggedValue::True());
204     }
205     num = 7;
206     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
207         auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
208         callInfo->SetFunction(JSTaggedValue::Undefined());
209         callInfo->SetThis(deque.GetTaggedValue());
210         callInfo->SetCallArg(0, JSTaggedValue(i + 8));
211 
212         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
213         JSTaggedValue result = ContainersDeque::Has(callInfo);
214         TestHelper::TearDownFrame(thread, prev);
215         EXPECT_EQ(result, JSTaggedValue::False());
216     }
217 }
218 
HWTEST_F_L0(ContainersDequeTest,PopFirst)219 HWTEST_F_L0(ContainersDequeTest, PopFirst)
220 {
221     constexpr uint32_t NODE_NUMBERS = 8;
222     JSHandle<JSAPIDeque> deque = CreateJSAPIDeque();
223     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
224         auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
225         callInfo->SetFunction(JSTaggedValue::Undefined());
226         callInfo->SetThis(deque.GetTaggedValue());
227         callInfo->SetCallArg(0, JSTaggedValue(i));
228 
229         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
230         ContainersDeque::InsertFront(callInfo);
231         TestHelper::TearDownFrame(thread, prev);
232         EXPECT_EQ(ContainersDeque::PopFirst(callInfo), JSTaggedValue(i));
233     }
234 }
235 
HWTEST_F_L0(ContainersDequeTest,PopLast)236 HWTEST_F_L0(ContainersDequeTest, PopLast)
237 {
238     constexpr uint32_t NODE_NUMBERS = 8;
239     JSHandle<JSAPIDeque> deque = CreateJSAPIDeque();
240     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
241         auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
242         callInfo->SetFunction(JSTaggedValue::Undefined());
243         callInfo->SetThis(deque.GetTaggedValue());
244         callInfo->SetCallArg(0, JSTaggedValue(i));
245 
246         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
247         ContainersDeque::InsertEnd(callInfo);
248         TestHelper::TearDownFrame(thread, prev);
249         EXPECT_EQ(ContainersDeque::PopLast(callInfo), JSTaggedValue(i));
250     }
251 }
252 
HWTEST_F_L0(ContainersDequeTest,ForEach)253 HWTEST_F_L0(ContainersDequeTest, ForEach)
254 {
255     constexpr uint32_t NODE_NUMBERS = 8;
256     JSHandle<JSAPIDeque> deque = CreateJSAPIDeque();
257     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
258             auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
259             callInfo->SetFunction(JSTaggedValue::Undefined());
260             callInfo->SetThis(deque.GetTaggedValue());
261             callInfo->SetCallArg(0, JSTaggedValue(i));
262 
263             [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
264             ContainersDeque::InsertEnd(callInfo);
265             TestHelper::TearDownFrame(thread, prev);
266     }
267     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
268     JSHandle<JSAPIDeque> dlist = CreateJSAPIDeque();
269     {
270         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
271         JSHandle<JSFunction> func = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForEachFunc));
272         auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
273         callInfo->SetFunction(JSTaggedValue::Undefined());
274         callInfo->SetThis(deque.GetTaggedValue());
275         callInfo->SetCallArg(0, func.GetTaggedValue());
276         callInfo->SetCallArg(1, dlist.GetTaggedValue());
277 
278         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
279         ContainersDeque::ForEach(callInfo);
280         TestHelper::TearDownFrame(thread, prev);
281     }
282 }
283 
HWTEST_F_L0(ContainersDequeTest,ProxyOfGetSize)284 HWTEST_F_L0(ContainersDequeTest, ProxyOfGetSize)
285 {
286     constexpr uint32_t NODE_NUMBERS = 10;
287     JSHandle<JSAPIDeque> deque = CreateJSAPIDeque();
288     auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
289     callInfo->SetFunction(JSTaggedValue::Undefined());
290     JSHandle<JSProxy> proxy = CreateJSProxyHandle(thread);
291     proxy->SetTarget(thread, deque.GetTaggedValue());
292     callInfo->SetThis(proxy.GetTaggedValue());
293 
294     for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
295         callInfo->SetCallArg(0, JSTaggedValue(i));
296         callInfo->SetCallArg(1, JSTaggedValue(i + 1));
297         [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
298         ContainersDeque::InsertFront(callInfo);
299         TestHelper::TearDownFrame(thread, prev);
300 
301         [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo);
302         JSTaggedValue retult = ContainersDeque::GetSize(callInfo);
303         TestHelper::TearDownFrame(thread, prev1);
304         EXPECT_EQ(retult, JSTaggedValue(i + 1));
305     }
306 }
307 
HWTEST_F_L0(ContainersDequeTest,ExceptionReturn)308 HWTEST_F_L0(ContainersDequeTest, ExceptionReturn)
309 {
310     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, InsertFront);
311     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, InsertEnd);
312     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, GetFirst);
313     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, GetLast);
314     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, Has);
315     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, PopFirst);
316     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, PopLast);
317     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, ForEach);
318     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, GetIteratorObj);
319     CONTAINERS_API_TYPE_MISMATCH_EXCEPTION_TEST(ContainersDeque, GetSize);
320 }
321 }  // namespace panda::test
322