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