1 /*
2 * Copyright (c) 2021 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/pending_job.h"
17
18 #include "ecmascript/base/builtins_base.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_promise.h"
21 #include "ecmascript/tagged_array.h"
22 #include "ecmascript/tests/test_helper.h"
23
24 using namespace panda::ecmascript;
25 using namespace panda::ecmascript::base;
26
27 namespace panda::test {
28 using PendingJob = ecmascript::job::PendingJob;
29 class PendingJobTest : public testing::Test {
30 public:
SetUpTestCase()31 static void SetUpTestCase()
32 {
33 GTEST_LOG_(INFO) << "SetUpTestCase";
34 }
35
TearDownTestCase()36 static void TearDownTestCase()
37 {
38 GTEST_LOG_(INFO) << "TearDownCase";
39 }
40
SetUp()41 void SetUp() override
42 {
43 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
44 }
45
TearDown()46 void TearDown() override
47 {
48 TestHelper::DestroyEcmaVMWithScope(instance, scope);
49 }
50
51 EcmaVM *instance {nullptr};
52 EcmaHandleScope *scope {nullptr};
53 JSThread *thread {nullptr};
54 };
55
56 /**
57 * @tc.name: GetJob
58 * @tc.desc: Check whether the result returned through "GetJob" function is within expectations.
59 * @tc.type: FUNC
60 * @tc.require:
61 */
HWTEST_F_L0(PendingJobTest,GetJob)62 HWTEST_F_L0(PendingJobTest, GetJob)
63 {
64 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
65 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
66
67 JSHandle<TaggedArray> handleArgv = factory->NewTaggedArray(0);
68 JSHandle<JSFunction> handleFunc = factory->NewJSFunction(env);
69
70 JSHandle<JSTaggedValue> handlePendingJobVal(factory->NewPendingJob(handleFunc, handleArgv));
71 EXPECT_TRUE(handlePendingJobVal->IsPendingJob());
72 JSHandle<PendingJob> handlePendingJob(handlePendingJobVal);
73 EXPECT_TRUE(handlePendingJob->GetJob().IsJSFunction());
74
75 JSHandle<JSFunction> handleNativeFunc(env->GetTypedArrayFunction());
76 handlePendingJob->SetJob(thread, handleNativeFunc.GetTaggedValue());
77 EXPECT_EQ(JSTaggedValue::SameValue(handlePendingJob->GetJob(), handleNativeFunc.GetTaggedValue()), true);
78 }
79
80 /**
81 * @tc.name: GetArguments
82 * @tc.desc: Check whether the result returned through "GetArguments" function is within expectations.
83 * @tc.type: FUNC
84 * @tc.require:
85 */
HWTEST_F_L0(PendingJobTest,GetArguments)86 HWTEST_F_L0(PendingJobTest, GetArguments)
87 {
88 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
89 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
90
91 JSHandle<TaggedArray> handleArgv1 = factory->NewTaggedArray(0);
92 JSHandle<JSFunction> handleFunc = factory->NewJSFunction(env);
93
94 JSHandle<JSTaggedValue> handlePendingJobVal(factory->NewPendingJob(handleFunc, handleArgv1));
95 EXPECT_TRUE(handlePendingJobVal->IsPendingJob());
96 JSHandle<PendingJob> handlePendingJob(handlePendingJobVal);
97 EXPECT_TRUE(handlePendingJob->GetArguments().IsTaggedArray());
98
99 JSHandle<TaggedArray> handleArgv2 = factory->NewTaggedArray(1);
100 handleArgv2->Set(thread, 0, JSTaggedValue(1));
101 handlePendingJob->SetArguments(thread, handleArgv2.GetTaggedValue());
102
103 JSHandle<TaggedArray> resultArray(thread, handlePendingJob->GetArguments());
104 EXPECT_EQ(resultArray->GetLength(), 1U);
105 EXPECT_EQ(resultArray->Get(0).GetInt(), 1);
106 }
107
108 /**
109 * @tc.name: ExecutePendingJob_001
110 * @tc.desc: Get a function called PromiseReactionJob from env.According to the definition of function,define a
111 * TaggedArray object with length of two.set the required value and define a pendingjob object according
112 * to both.the pendingjob object call "ExecutePendingJob" function to execute the method of function and
113 * return the value of the method.
114 * @tc.type: FUNC
115 * @tc.require:
116 */
HWTEST_F_L0(PendingJobTest,ExecutePendingJob_001)117 HWTEST_F_L0(PendingJobTest, ExecutePendingJob_001)
118 {
119 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
120 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
121 JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
122
123 JSHandle<PromiseCapability> capbility = JSPromise::NewPromiseCapability(thread, promiseFunc);
124 JSHandle<JSTaggedValue> reject(thread, capbility->GetReject());
125
126 JSHandle<PromiseReaction> rejectReaction = factory->NewPromiseReaction();
127 rejectReaction->SetPromiseCapability(thread, capbility.GetTaggedValue());
128 rejectReaction->SetHandler(thread, reject.GetTaggedValue());
129
130 JSHandle<JSFunction> promiseReactionsJob(env->GetPromiseReactionJob());
131 JSHandle<TaggedArray> handleArgv = factory->NewTaggedArray(2);
132 handleArgv->Set(thread, 0, rejectReaction.GetTaggedValue());
133 handleArgv->Set(thread, 1, JSTaggedValue(44));
134
135 JSHandle<PendingJob> handlePendingJob = factory->NewPendingJob(promiseReactionsJob, handleArgv);
136 JSTaggedValue callResult = PendingJob::ExecutePendingJob(handlePendingJob, thread);
137 EXPECT_EQ(callResult, JSTaggedValue::Undefined());
138 JSHandle<JSPromise> jsPromise(thread, capbility->GetPromise());
139 EXPECT_EQ(jsPromise->GetPromiseState(), PromiseState::REJECTED);
140 EXPECT_EQ(JSTaggedValue::SameValue(jsPromise->GetPromiseResult(), JSTaggedValue(44)), true);
141 }
142
143 /**
144 * @tc.name: ExecutePendingJob_002
145 * @tc.desc: Get a function called PromiseReactionJob from env.According to the definition of function,define a
146 * TaggedArray object with length of two.set the required value and define a pendingjob object according
147 * to both.the pendingjob object call "ExecutePendingJob" function to execute the method of function and
148 * return the value of the method.
149 * @tc.type: FUNC
150 * @tc.require:
151 */
HWTEST_F_L0(PendingJobTest,ExecutePendingJob_002)152 HWTEST_F_L0(PendingJobTest, ExecutePendingJob_002)
153 {
154 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
155 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
156 JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
157 JSHandle<JSTaggedValue> paramMsg(factory->NewFromASCII("resolve"));
158
159 JSHandle<PromiseCapability> capbility = JSPromise::NewPromiseCapability(thread, promiseFunc);
160 JSHandle<JSTaggedValue> resolve(thread, capbility->GetResolve());
161
162 JSHandle<PromiseReaction> fulfillReaction = factory->NewPromiseReaction();
163 fulfillReaction->SetPromiseCapability(thread, capbility.GetTaggedValue());
164 fulfillReaction->SetHandler(thread, resolve.GetTaggedValue());
165
166 JSHandle<JSFunction> promiseReactionsJob(env->GetPromiseReactionJob());
167 JSHandle<TaggedArray> handleArgv = factory->NewTaggedArray(2);
168 handleArgv->Set(thread, 0, fulfillReaction.GetTaggedValue());
169 handleArgv->Set(thread, 1, paramMsg.GetTaggedValue());
170
171 JSHandle<PendingJob> handlePendingJob = factory->NewPendingJob(promiseReactionsJob, handleArgv);
172 JSTaggedValue callResult = PendingJob::ExecutePendingJob(handlePendingJob, thread);
173 EXPECT_EQ(callResult, JSTaggedValue::Undefined());
174 JSHandle<JSPromise> jsPromise(thread, capbility->GetPromise());
175 EXPECT_EQ(jsPromise->GetPromiseState(), PromiseState::FULFILLED);
176 EXPECT_EQ(JSTaggedValue::SameValue(jsPromise->GetPromiseResult(), paramMsg.GetTaggedValue()), true);
177 }
178
179 /**
180 * @tc.name: ExecutePendingJob_003
181 * @tc.desc: Get a function called PromiseReactionJob from env.According to the definition of function,define a
182 * TaggedArray object with length of two.set the required value and define a pendingjob object according
183 * to both.the pendingjob object call "ExecutePendingJob" function to execute the method of function and
184 * return the value of the method.
185 * @tc.type: FUNC
186 * @tc.require:
187 */
HWTEST_F_L0(PendingJobTest,ExecutePendingJob_003)188 HWTEST_F_L0(PendingJobTest, ExecutePendingJob_003)
189 {
190 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
191 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
192 JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
193 JSHandle<JSTaggedValue> paramMsg(factory->NewFromASCII("Thrower"));
194
195 JSHandle<PromiseCapability> capbility = JSPromise::NewPromiseCapability(thread, promiseFunc);
196 JSHandle<PromiseReaction> rejectReaction = factory->NewPromiseReaction();
197 rejectReaction->SetPromiseCapability(thread, capbility.GetTaggedValue());
198 rejectReaction->SetHandler(thread, paramMsg.GetTaggedValue());
199
200 JSHandle<JSFunction> promiseReactionsJob(env->GetPromiseReactionJob());
201 JSHandle<TaggedArray> handleArgv = factory->NewTaggedArray(2);
202 handleArgv->Set(thread, 0, rejectReaction.GetTaggedValue());
203 handleArgv->Set(thread, 1, JSTaggedValue::Undefined());
204
205 JSHandle<PendingJob> handlePendingJob = factory->NewPendingJob(promiseReactionsJob, handleArgv);
206 JSTaggedValue callResult = PendingJob::ExecutePendingJob(handlePendingJob, thread);
207 EXPECT_EQ(callResult, JSTaggedValue::Undefined());
208 JSHandle<JSPromise> jsPromise(thread, capbility->GetPromise());
209 EXPECT_EQ(jsPromise->GetPromiseState(), PromiseState::REJECTED);
210 EXPECT_EQ(JSTaggedValue::SameValue(jsPromise->GetPromiseResult(), JSTaggedValue::Undefined()), true);
211 }
212
TestPromiseOnResolved(EcmaRuntimeCallInfo * argv)213 JSTaggedValue TestPromiseOnResolved(EcmaRuntimeCallInfo *argv)
214 {
215 auto factory = argv->GetThread()->GetEcmaVM()->GetFactory();
216 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
217 EXPECT_TRUE(result->IsPromiseReaction());
218 auto handlerMsg = factory->NewFromASCII("after_resolve");
219 JSHandle<PromiseReaction> reaction = JSHandle<PromiseReaction>::Cast(result);
220 JSHandle<JSTaggedValue> handler(argv->GetThread(), reaction->GetHandler());
221 EXPECT_EQ(JSTaggedValue::SameValue(handler.GetTaggedValue(), handlerMsg.GetTaggedValue()), true);
222 return JSTaggedValue::Undefined();
223 }
224
225 /**
226 * @tc.name: ExecutePendingJob_004
227 * @tc.desc: Create a function called TestPromiseOnResolved.According to the definition of function,define a TaggedArray
228 * object with length of two.set the required value and define a pendingjob object according to both.
229 * the pendingjob object call "ExecutePendingJob" function to execute the method of function and return the
230 * value of the method.
231 * @tc.type: FUNC
232 * @tc.require:
233 */
HWTEST_F_L0(PendingJobTest,ExecutePendingJob_004)234 HWTEST_F_L0(PendingJobTest, ExecutePendingJob_004)
235 {
236 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
237 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
238 JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
239 JSHandle<JSTaggedValue> paramMsg(factory->NewFromASCII("after_resolve"));
240
241 JSHandle<PromiseCapability> capbility = JSPromise::NewPromiseCapability(thread, promiseFunc);
242 JSHandle<JSTaggedValue> resolve(thread, capbility->GetResolve());
243
244 JSHandle<PromiseReaction> fulfillReaction = factory->NewPromiseReaction();
245 fulfillReaction->SetPromiseCapability(thread, capbility.GetTaggedValue());
246 fulfillReaction->SetHandler(thread, paramMsg.GetTaggedValue());
247
248 JSHandle<JSFunction> testPromiseResolved =
249 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseOnResolved));
250 JSHandle<TaggedArray> handleArgv = factory->NewTaggedArray(2);
251 handleArgv->Set(thread, 0, fulfillReaction.GetTaggedValue());
252 handleArgv->Set(thread, 1, JSTaggedValue::Undefined());
253
254 JSHandle<PendingJob> handlePendingJob = factory->NewPendingJob(testPromiseResolved, handleArgv);
255 JSTaggedValue callResult = PendingJob::ExecutePendingJob(handlePendingJob, thread);
256 EXPECT_EQ(callResult, JSTaggedValue::Undefined());
257 JSHandle<JSPromise> jsPromise(thread, capbility->GetPromise());
258 EXPECT_EQ(jsPromise->GetPromiseState(), PromiseState::PENDING);
259 EXPECT_EQ(jsPromise->GetPromiseResult().IsUndefined(), true);
260 }
261
TestPromiseResolveThenableJob(EcmaRuntimeCallInfo * argv)262 JSTaggedValue TestPromiseResolveThenableJob(EcmaRuntimeCallInfo *argv)
263 {
264 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
265 EXPECT_TRUE(result->IsJSFunction());
266 JSHandle<JSTaggedValue> undefined(argv->GetThread(), JSTaggedValue::Undefined());
267 EcmaRuntimeCallInfo *info =
268 EcmaInterpreter::NewRuntimeCallInfo(argv->GetThread(), result, undefined, undefined, 1);
269 info->SetCallArg(JSTaggedValue(44)); // 44 : 44 promise result
270 return JSFunction::Call(info);
271 }
272
273 /**
274 * @tc.name: ExecutePendingJob_005
275 * @tc.desc: Get a function called promiseresolvethenablejob from env. According to the definition of function,
276 * define a TaggedArray object with length of three.set the required value and define a pendingjob object
277 * according to both.The pendingjob object call "ExecutePendingJob" function to execute the method of function
278 * and return the value of the method.
279 * @tc.type: FUNC
280 * @tc.require:
281 */
HWTEST_F_L0(PendingJobTest,ExecutePendingJob_005)282 HWTEST_F_L0(PendingJobTest, ExecutePendingJob_005)
283 {
284 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
285 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
286 JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
287 JSHandle<JSTaggedValue> paramMsg(thread, JSTaggedValue::Undefined());
288
289 JSHandle<JSPromise> jsPromise =
290 JSHandle<JSPromise>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(promiseFunc), promiseFunc));
291 JSHandle<JSFunction> testPromiseResolveThenableJob =
292 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseResolveThenableJob));
293
294 JSHandle<JSFunction> promiseResolveThenableJob(env->GetPromiseResolveThenableJob());
295 JSHandle<TaggedArray> handleArgv = factory->NewTaggedArray(3);
296 handleArgv->Set(thread, 0, jsPromise.GetTaggedValue());
297 handleArgv->Set(thread, 1, paramMsg.GetTaggedValue());
298 handleArgv->Set(thread, 2, testPromiseResolveThenableJob.GetTaggedValue());
299
300 JSHandle<PendingJob> handlePendingJob = factory->NewPendingJob(promiseResolveThenableJob, handleArgv);
301 JSTaggedValue callResult = PendingJob::ExecutePendingJob(handlePendingJob, thread);
302 EXPECT_EQ(callResult, JSTaggedValue::Undefined());
303
304 EXPECT_EQ(jsPromise->GetPromiseState(), PromiseState::FULFILLED);
305 EXPECT_EQ(JSTaggedValue::SameValue(jsPromise->GetPromiseResult(), JSTaggedValue(44)), true);
306 }
307 } // namespace panda::test
308