• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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/jobs/micro_job_queue.h"
17 
18 #include "ecmascript/jobs/pending_job.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_promise.h"
21 #include "ecmascript/tagged_queue.h"
22 #include "ecmascript/tests/test_helper.h"
23 
24 using namespace panda::ecmascript;
25 
26 namespace panda::test {
27 using MicroJobQueue = ecmascript::job::MicroJobQueue;
28 using PendingJob = ecmascript::job::PendingJob;
29 using QueueType = job::QueueType;
30 class MicroJobQueueTest : public testing::Test {
31 public:
SetUpTestCase()32     static void SetUpTestCase()
33     {
34         GTEST_LOG_(INFO) << "SetUpTestCase";
35     }
36 
TearDownTestCase()37     static void TearDownTestCase()
38     {
39         GTEST_LOG_(INFO) << "TearDownCase";
40     }
41 
SetUp()42     void SetUp() override
43     {
44         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
45     }
46 
TearDown()47     void TearDown() override
48     {
49         TestHelper::DestroyEcmaVMWithScope(instance, scope);
50     }
51 
52     EcmaVM *instance {nullptr};
53     EcmaHandleScope *scope {nullptr};
54     JSThread *thread {nullptr};
55 };
56 
57 /**
58  * @tc.name: GetJobQueue
59  * @tc.desc: Check whether the result returned through "GetPromiseJobQueue" and "GetScriptJobQueue" function
60  *           is within expectations.
61  * @tc.type: FUNC
62  * @tc.require:
63  */
HWTEST_F_L0(MicroJobQueueTest,GetJobQueue)64 HWTEST_F_L0(MicroJobQueueTest, GetJobQueue)
65 {
66     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
67     uint32_t capacity = 4;
68     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(123));
69 
70     JSHandle<TaggedQueue> handlePromiseQueue = factory->NewTaggedQueue(capacity);
71     TaggedQueue::PushFixedQueue(thread, handlePromiseQueue, handleValue);
72     JSHandle<TaggedQueue> handleScriptQueue = factory->NewTaggedQueue(capacity - 1);
73 
74     JSHandle<MicroJobQueue> handleMicroJobQueue = factory->NewMicroJobQueue();
75     EXPECT_TRUE(*handleMicroJobQueue != nullptr);
76 
77     handleMicroJobQueue->SetPromiseJobQueue(thread, handlePromiseQueue.GetTaggedValue());
78     handleMicroJobQueue->SetScriptJobQueue(thread, handleScriptQueue.GetTaggedValue());
79 
80     JSHandle<TaggedQueue> promiseQueue(thread, handleMicroJobQueue->GetPromiseJobQueue(thread));
81     JSHandle<TaggedQueue> scriptQueue(thread, handleMicroJobQueue->GetScriptJobQueue(thread));
82 
83     EXPECT_EQ(promiseQueue->Size(thread), 1U);
84     EXPECT_EQ(scriptQueue->Size(thread), 0U);
85 
86     EXPECT_EQ(promiseQueue->Back(thread).GetInt(), 123);
87     EXPECT_TRUE(scriptQueue->Back(thread).IsHole());
88 }
89 
90 /**
91  * @tc.name: EnqueuePromiseJob
92  * @tc.desc: Get a JobQueue called MicroJobQueue from vm.define a function and TaggedArray object,call EnqueuePromiseJob
93  *           function to enter the "function" and TaggedArray object into the promise job queueof the MicroJobQueue,then
94  *           check whether the object out of the queue is the same as the object in the queue.
95  * @tc.type: FUNC
96  * @tc.require:
97  */
HWTEST_F_L0(MicroJobQueueTest,EnqueuePromiseJob)98 HWTEST_F_L0(MicroJobQueueTest, EnqueuePromiseJob)
99 {
100     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
101     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
102     JSHandle<MicroJobQueue> handleMicrojob = thread->GetEcmaVM()->GetMicroJobQueue();
103     JSHandle<TaggedQueue> originalPromiseQueue(thread, handleMicrojob->GetPromiseJobQueue(thread));
104     JSHandle<JSTaggedValue> scriptQueue(thread, handleMicrojob->GetScriptJobQueue(thread));
105 
106     JSHandle<TaggedArray> arguments = factory->NewTaggedArray(2);
107     arguments->Set(thread, 0, JSTaggedValue::Undefined());
108     arguments->Set(thread, 1, JSTaggedValue::Undefined());
109     JSHandle<JSFunction> promiseReactionsJob(globalEnv->GetPromiseReactionJob());
110 
111     QueueType type = QueueType::QUEUE_PROMISE;
112     MicroJobQueue::EnqueueJob(thread, handleMicrojob, type, promiseReactionsJob, arguments);
113 
114     JSHandle<TaggedQueue> promiseQueue(thread, handleMicrojob->GetPromiseJobQueue(thread));
115     EXPECT_EQ(JSTaggedValue::SameValue(thread, promiseQueue.GetTaggedValue(), originalPromiseQueue.GetTaggedValue()),
116               false);
117     EXPECT_EQ(JSTaggedValue::SameValue(thread, handleMicrojob->GetScriptJobQueue(thread), scriptQueue.GetTaggedValue()),
118               true);
119 
120     JSTaggedValue result = promiseQueue->Pop(thread);
121     EXPECT_TRUE(result.IsPendingJob());
122 
123     JSHandle<PendingJob> pendingJob(thread, result);
124     EXPECT_EQ(JSTaggedValue::SameValue(thread, pendingJob->GetJob(thread), promiseReactionsJob.GetTaggedValue()), true);
125     EXPECT_EQ(JSTaggedValue::SameValue(thread, pendingJob->GetArguments(thread), arguments.GetTaggedValue()), true);
126 }
127 
128 /**
129  * @tc.name: EnqueuePromiseJob
130  * @tc.desc: Get a JobQueue called MicroJobQueue from vm.define a function and TaggedArray object,call EnqueuePromiseJob
131  *           function to enter the "function" and TaggedArray object into the script job queue of the MicroJobQueue,then
132  *           check whether the object out of the queue is the same as the object in the queue.
133  * @tc.type: FUNC
134  * @tc.require:
135  */
HWTEST_F_L0(MicroJobQueueTest,EnqueueScriptJob)136 HWTEST_F_L0(MicroJobQueueTest, EnqueueScriptJob)
137 {
138     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
139     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
140     JSHandle<MicroJobQueue> handleMicrojob = thread->GetEcmaVM()->GetMicroJobQueue();
141     JSHandle<JSTaggedValue> promiseQueue(thread, handleMicrojob->GetPromiseJobQueue(thread));
142     JSHandle<TaggedQueue> originalScriptQueue(thread, handleMicrojob->GetScriptJobQueue(thread));
143 
144     JSHandle<TaggedArray> arguments1 = factory->NewTaggedArray(2);
145     JSHandle<JSFunction> promiseReactionsJob(globalEnv->GetPromiseReactionJob());
146 
147     QueueType type = QueueType::QUEUE_SCRIPT;
148     MicroJobQueue::EnqueueJob(thread, handleMicrojob, type, promiseReactionsJob, arguments1);
149 
150     JSHandle<JSFunction> promiseResolveThenableJob(globalEnv->GetPromiseResolveThenableJob());
151     JSHandle<TaggedArray> arguments2 = factory->NewTaggedArray(2);
152     arguments2->Set(thread, 0, JSTaggedValue(134));
153     arguments2->Set(thread, 1, JSTaggedValue::Undefined());
154     MicroJobQueue::EnqueueJob(thread, handleMicrojob, type, promiseResolveThenableJob, arguments2);
155 
156     JSHandle<TaggedQueue> scriptQueue(thread, handleMicrojob->GetScriptJobQueue(thread));
157     EXPECT_EQ(JSTaggedValue::SameValue(thread, scriptQueue.GetTaggedValue(), originalScriptQueue.GetTaggedValue()),
158               false);
159     EXPECT_EQ(
160         JSTaggedValue::SameValue(thread, handleMicrojob->GetPromiseJobQueue(thread), promiseQueue.GetTaggedValue()),
161         true);
162 
163     JSTaggedValue result1 = scriptQueue->Pop(thread);
164     EXPECT_TRUE(result1.IsPendingJob());
165     // FIFO
166     JSHandle<PendingJob> pendingJob1(thread, result1);
167     EXPECT_EQ(JSTaggedValue::SameValue(thread, pendingJob1->GetJob(thread), promiseReactionsJob.GetTaggedValue()),
168               true);
169     EXPECT_EQ(JSTaggedValue::SameValue(thread, pendingJob1->GetArguments(thread), arguments1.GetTaggedValue()), true);
170 
171     JSTaggedValue result2 = scriptQueue->Pop(thread);
172     EXPECT_TRUE(result2.IsPendingJob());
173     JSHandle<PendingJob> pendingJob2(thread, result2);
174     EXPECT_EQ(JSTaggedValue::SameValue(thread, pendingJob2->GetJob(thread), promiseResolveThenableJob.GetTaggedValue()),
175               true);
176     EXPECT_EQ(JSTaggedValue::SameValue(thread, pendingJob2->GetArguments(thread), arguments2.GetTaggedValue()), true);
177 }
178 
179 /**
180  * @tc.name: ExecutePendingJob_001
181  * @tc.desc: Get a JobQueue called MicroJobQueue from vm and get a function called PromiseReactionJob from env.
182  *           According to the definition of function,define a TaggedArray object with length of two.set the required
183  *           value and enter "function" and TaggedArray object into the promise job queue.Calling "ExecutePendingJob"
184  *           function to execute the method of function and return the value of the method.
185  * @tc.type: FUNC
186  * @tc.require:
187  */
HWTEST_F_L0(MicroJobQueueTest,ExecutePendingJob_001)188 HWTEST_F_L0(MicroJobQueueTest, ExecutePendingJob_001)
189 {
190     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
191     auto env = thread->GetEcmaVM()->GetGlobalEnv();
192     JSHandle<JSFunction> promiseReactionsJob(env->GetPromiseReactionJob());
193     JSHandle<MicroJobQueue> handleMicrojob = thread->GetEcmaVM()->GetMicroJobQueue();
194 
195     JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
196     JSHandle<PromiseCapability> capbility = JSPromise::NewPromiseCapability(thread, promiseFunc);
197     JSHandle<JSTaggedValue> resolve(thread, capbility->GetResolve(thread));
198 
199     JSHandle<PromiseReaction> fulfillReaction = factory->NewPromiseReaction();
200     fulfillReaction->SetPromiseCapability(thread, capbility.GetTaggedValue());
201     fulfillReaction->SetHandler(thread, resolve.GetTaggedValue());
202 
203     JSHandle<TaggedArray> arguments = factory->NewTaggedArray(2);
204     arguments->Set(thread, 0, fulfillReaction.GetTaggedValue());
205     arguments->Set(thread, 1, JSTaggedValue::Undefined());
206     MicroJobQueue::EnqueueJob(thread, handleMicrojob, QueueType::QUEUE_PROMISE, promiseReactionsJob, arguments);
207 
208     JSHandle<PromiseReaction> rejectReaction = factory->NewPromiseReaction();
209     rejectReaction->SetPromiseCapability(thread, capbility.GetTaggedValue());
210     rejectReaction->SetHandler(thread, resolve.GetTaggedValue());
211 
212     // get into the promise queue and execute PendingJob
213     if (!thread->HasPendingException()) {
214         MicroJobQueue::ExecutePendingJob(thread, handleMicrojob);
215     }
216     JSHandle<JSPromise> jsPromise(thread, capbility->GetPromise(thread));
217     EXPECT_EQ(jsPromise->GetPromiseState(), PromiseState::FULFILLED);
218     EXPECT_EQ(JSTaggedValue::SameValue(thread, jsPromise->GetPromiseResult(thread), JSTaggedValue::Undefined()), true);
219 }
220 
221 /**
222  * @tc.name: ExecutePendingJob_002
223  * @tc.desc: Get a JobQueue called MicroJobQueue from vm and get a function called PromiseReactionJob from env.
224  *           According to the definition of function,define a TaggedArray object with length of two.set the required
225  *           value and enter the "function" and TaggedArray object into the script job queue and promise job queue.
226  *           Calling "ExecutePendingJob" function to execute the method of Two queue function and return the value
227  *           of the method.
228  * @tc.type: FUNC
229  * @tc.require:
230  */
HWTEST_F_L0(MicroJobQueueTest,ExecutePendingJob_002)231 HWTEST_F_L0(MicroJobQueueTest, ExecutePendingJob_002)
232 {
233     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
234     auto env = thread->GetEcmaVM()->GetGlobalEnv();
235     JSHandle<JSFunction> promiseReactionsJob(env->GetPromiseReactionJob());
236     JSHandle<MicroJobQueue> handleMicrojob = thread->GetEcmaVM()->GetMicroJobQueue();
237 
238     JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
239     JSHandle<PromiseCapability> capbility1 = JSPromise::NewPromiseCapability(thread, promiseFunc);
240     JSHandle<JSTaggedValue> resolve(thread, capbility1->GetResolve(thread));
241 
242     JSHandle<PromiseReaction> fulfillReaction = factory->NewPromiseReaction();
243     fulfillReaction->SetPromiseCapability(thread, capbility1.GetTaggedValue());
244     fulfillReaction->SetHandler(thread, resolve.GetTaggedValue());
245 
246     JSHandle<TaggedArray> arguments1 = factory->NewTaggedArray(2);
247     arguments1->Set(thread, 0, fulfillReaction.GetTaggedValue());
248     arguments1->Set(thread, 1, JSTaggedValue::Undefined());
249     MicroJobQueue::EnqueueJob(thread, handleMicrojob, QueueType::QUEUE_PROMISE, promiseReactionsJob, arguments1);
250 
251     JSHandle<PromiseCapability> capbility2 = JSPromise::NewPromiseCapability(thread, promiseFunc);
252     JSHandle<JSTaggedValue> reject(thread, capbility2->GetReject(thread));
253     JSHandle<PromiseReaction> rejectReaction = factory->NewPromiseReaction();
254     rejectReaction->SetPromiseCapability(thread, capbility2.GetTaggedValue());
255     rejectReaction->SetHandler(thread, reject.GetTaggedValue());
256 
257     JSHandle<TaggedArray> arguments2 = factory->NewTaggedArray(2);
258     arguments2->Set(thread, 0, rejectReaction.GetTaggedValue());
259     arguments2->Set(thread, 1, JSTaggedValue(32));
260     MicroJobQueue::EnqueueJob(thread, handleMicrojob, QueueType::QUEUE_SCRIPT, promiseReactionsJob, arguments2);
261 
262     // get into the promise queue and execute PendingJob
263     if (!thread->HasPendingException()) {
264         MicroJobQueue::ExecutePendingJob(thread, handleMicrojob);
265     }
266     JSHandle<JSPromise> resolvePromise(thread, capbility1->GetPromise(thread));
267     EXPECT_EQ(resolvePromise->GetPromiseState(), PromiseState::FULFILLED);
268     EXPECT_EQ(JSTaggedValue::SameValue(thread, resolvePromise->GetPromiseResult(thread), JSTaggedValue::Undefined()),
269               true);
270 
271     JSHandle<JSPromise> rejectPromise(thread, capbility2->GetPromise(thread));
272     EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
273     EXPECT_EQ(JSTaggedValue::SameValue(thread, rejectPromise->GetPromiseResult(thread), JSTaggedValue(32)), true);
274 }
275 } // namespace panda::test
276