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/builtins/builtins_promise.h"
17
18 #include "ecmascript/builtins/builtins_array.h"
19 #include "ecmascript/ecma_string.h"
20 #include "ecmascript/ecma_vm.h"
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/jobs/micro_job_queue.h"
23 #include "ecmascript/js_array.h"
24 #include "ecmascript/js_promise.h"
25 #include "ecmascript/js_tagged_value-inl.h"
26 #include "ecmascript/js_tagged_value.h"
27 #include "ecmascript/js_thread.h"
28 #include "ecmascript/object_factory.h"
29 #include "ecmascript/tests/test_helper.h"
30
31 using namespace panda::ecmascript;
32 using namespace panda::ecmascript::builtins;
33
34 namespace panda::test {
35 using BuiltinsBase = panda::ecmascript::base::BuiltinsBase;
36 using JSArray = panda::ecmascript::JSArray;
37
38 class BuiltinsPromiseTest : public BaseTestWithScope<false> {
39 };
40
41 // native function for race2 then_on_rejected()
TestPromiseRaceThenOnRejectd(EcmaRuntimeCallInfo *argv)42 JSTaggedValue TestPromiseRaceThenOnRejectd(EcmaRuntimeCallInfo *argv)
43 {
44 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
45 // 12345 : test case
46 EXPECT_EQ(JSTaggedValue::SameValue(result.GetTaggedValue(), JSTaggedValue(12345)), true);
47 return JSTaggedValue::Undefined();
48 }
49
50 // native function for all then_on_resolved()
TestPromiseAllThenOnResolved(EcmaRuntimeCallInfo *argv)51 JSTaggedValue TestPromiseAllThenOnResolved(EcmaRuntimeCallInfo *argv)
52 {
53 JSHandle<JSTaggedValue> array = BuiltinsBase::GetCallArg(argv, 0);
54 JSHandle<JSObject> objectArray = JSHandle<JSObject>::Cast(array);
55 [[maybe_unused]] PropertyDescriptor desc(argv->GetThread());
56 [[maybe_unused]] bool result1 = JSObject::GetOwnProperty(
57 argv->GetThread(), objectArray, JSHandle<JSTaggedValue>(argv->GetThread(), JSTaggedValue(0)), desc);
58 EXPECT_TRUE(result1);
59 JSHandle<JSTaggedValue> value1 = desc.GetValue();
60 // 111 : test case
61 EXPECT_EQ(JSTaggedValue::SameValue(value1.GetTaggedValue(), JSTaggedValue(111)), true);
62 [[maybe_unused]] bool result2 = JSObject::GetOwnProperty(
63 argv->GetThread(), objectArray, JSHandle<JSTaggedValue>(argv->GetThread(), JSTaggedValue(1)), desc);
64 EXPECT_TRUE(result2);
65 JSHandle<JSTaggedValue> value2 = desc.GetValue();
66 // 222 : test case
67 EXPECT_EQ(JSTaggedValue::SameValue(value2.GetTaggedValue(), JSTaggedValue(222)), true);
68 return JSTaggedValue::Undefined();
69 }
70
71 // native function for catch catch_on_rejected()
TestPromiseCatch(EcmaRuntimeCallInfo *argv)72 JSTaggedValue TestPromiseCatch(EcmaRuntimeCallInfo *argv)
73 {
74 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
75 // 3 : test case
76 EXPECT_EQ(JSTaggedValue::SameValue(result.GetTaggedValue(), JSTaggedValue(3)), true);
77 return JSTaggedValue::Undefined();
78 }
79
80 // native function for then then_on_resolved()
TestPromiseThenOnResolved(EcmaRuntimeCallInfo *argv)81 JSTaggedValue TestPromiseThenOnResolved(EcmaRuntimeCallInfo *argv)
82 {
83 auto factory = argv->GetThread()->GetEcmaVM()->GetFactory();
84 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
85 auto expect = factory->NewFromASCII("resolve");
86 EXPECT_EQ(JSTaggedValue::SameValue(result.GetTaggedValue(), expect.GetTaggedValue()), true);
87 return JSTaggedValue::Undefined();
88 }
89
90 // native function for then then_on_rejected()
TestPromiseThenOnRejected(EcmaRuntimeCallInfo *argv)91 JSTaggedValue TestPromiseThenOnRejected(EcmaRuntimeCallInfo *argv)
92 {
93 auto factory = argv->GetThread()->GetEcmaVM()->GetFactory();
94 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
95 auto expect = factory->NewFromASCII("reject");
96 EXPECT_EQ(JSTaggedValue::SameValue(result.GetTaggedValue(), expect.GetTaggedValue()), true);
97 return JSTaggedValue::Undefined();
98 }
99
100 enum class AlgorithmType {
101 REJECT,
102 RESOLVE,
103 RACE,
104 ALL,
105 };
106
PromiseAlgorithm(JSThread *thread, JSHandle<JSFunction>& promise, JSTaggedValue arg, AlgorithmType type)107 JSTaggedValue PromiseAlgorithm(JSThread *thread, JSHandle<JSFunction>& promise, JSTaggedValue arg,
108 AlgorithmType type)
109 {
110 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
111 ecmaRuntimeCallInfo->SetFunction(promise.GetTaggedValue());
112 ecmaRuntimeCallInfo->SetThis(promise.GetTaggedValue());
113 ecmaRuntimeCallInfo->SetCallArg(0, arg);
114
115 auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
116 JSTaggedValue result;
117 switch (type) {
118 case AlgorithmType::REJECT:
119 result = BuiltinsPromise::Reject(ecmaRuntimeCallInfo);
120 break;
121 case AlgorithmType::RESOLVE:
122 result = BuiltinsPromise::Resolve(ecmaRuntimeCallInfo);
123 break;
124 case AlgorithmType::RACE:
125 result = BuiltinsPromise::Race(ecmaRuntimeCallInfo);
126 break;
127 case AlgorithmType::ALL:
128 result = BuiltinsPromise::All(ecmaRuntimeCallInfo);
129 break;
130 default:
131 break;
132 }
133
134 TestHelper::TearDownFrame(thread, prev);
135 return result;
136 }
137
ThanAlgorithm(JSThread *thread, JSHandle<JSPromise>& promise, JSTaggedValue arg1, JSTaggedValue arg2)138 JSTaggedValue ThanAlgorithm(JSThread *thread, JSHandle<JSPromise>& promise, JSTaggedValue arg1,
139 JSTaggedValue arg2)
140 {
141 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, promise.GetTaggedValue(), 8);
142 ecmaRuntimeCallInfo->SetFunction(promise.GetTaggedValue());
143 ecmaRuntimeCallInfo->SetThis(promise.GetTaggedValue());
144 ecmaRuntimeCallInfo->SetCallArg(0, arg1);
145 ecmaRuntimeCallInfo->SetCallArg(1, arg2);
146 auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
147 auto result = BuiltinsPromise::Then(ecmaRuntimeCallInfo);
148 TestHelper::TearDownFrame(thread, prev);
149 return result;
150 }
151 /*
152 * @tc.name: Reject1
153 * @tc.desc: The reject method receives a number.
154 * @tc.type: FUNC
155 */
HWTEST_F_L0(BuiltinsPromiseTest, Reject1)156 HWTEST_F_L0(BuiltinsPromiseTest, Reject1)
157 {
158 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
159
160 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
161 JSHandle<JSTaggedValue> paramMsg(thread, JSTaggedValue(3));
162
163 // /**
164 // * @tc.steps: var p1 = Promise.reject(3).
165 // */
166
167 auto result = PromiseAlgorithm(thread, promise, paramMsg.GetTaggedValue(), AlgorithmType::REJECT);
168 JSHandle<JSPromise> rejectPromise(thread, result);
169 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
170 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(3)), true);
171 }
172
173 /*
174 * @tc.name: Reject2
175 * @tc.desc: The reject method receives a promise object.
176 * @tc.type: FUNC
177 */
HWTEST_F_L0(BuiltinsPromiseTest, Reject2)178 HWTEST_F_L0(BuiltinsPromiseTest, Reject2)
179 {
180 ObjectFactory *factory = instance->GetFactory();
181 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
182
183 // constructor promise1
184 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
185 JSHandle<JSTaggedValue> paramMsg1 =
186 JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("Promise reject"));
187
188 /**
189 * @tc.steps: step1. var p1 = Promise.reject("Promise reject")
190 */
191 auto result = PromiseAlgorithm(thread, promise, paramMsg1.GetTaggedValue(), AlgorithmType::REJECT);
192 JSHandle<JSPromise> promise1(thread, result);
193 EXPECT_EQ(promise1->GetPromiseState(), PromiseState::REJECTED);
194 EXPECT_EQ(JSTaggedValue::SameValue(promise1->GetPromiseResult(), paramMsg1.GetTaggedValue()), true);
195
196 /**
197 * @tc.steps: step2. var p2 = Promise.reject(p1)
198 */
199 auto result1 = PromiseAlgorithm(thread, promise, promise1.GetTaggedValue(), AlgorithmType::REJECT);
200 JSHandle<JSPromise> promise2(thread, result1);
201 EXPECT_NE(*promise1, *promise2);
202 EXPECT_EQ(promise2->GetPromiseState(), PromiseState::REJECTED);
203 EXPECT_EQ(
204 JSTaggedValue::SameValue(promise2->GetPromiseResult(), JSTaggedValue(promise1.GetTaggedValue().GetRawData())),
205 true);
206 }
207
208 /*
209 * @tc.name: Resolve1
210 * @tc.desc: The resolve method receives a number.
211 * @tc.type: FUNC
212 */
HWTEST_F_L0(BuiltinsPromiseTest, Resolve1)213 HWTEST_F_L0(BuiltinsPromiseTest, Resolve1)
214 {
215 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
216
217 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
218 JSHandle<JSTaggedValue> paramMsg(thread, JSTaggedValue(5));
219
220 /**
221 * @tc.steps: step1. var p1 = Promise.resolve(12345)
222 */
223 auto result = PromiseAlgorithm(thread, promise, paramMsg.GetTaggedValue(), AlgorithmType::RESOLVE);
224 JSHandle<JSPromise> rejectPromise(thread, result);
225 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::FULFILLED);
226 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(5)), true);
227 }
228
229 /*
230 * @tc.name: Resolve2
231 * @tc.desc: The resolve method receives a promise object.
232 * @tc.type: FUNC
233 */
HWTEST_F_L0(BuiltinsPromiseTest, Resolve2)234 HWTEST_F_L0(BuiltinsPromiseTest, Resolve2)
235 {
236 ObjectFactory *factory = instance->GetFactory();
237 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
238
239 // constructor promise1
240 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
241 JSHandle<JSTaggedValue> paramMsg1 =
242 JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("Promise reject"));
243
244 /**
245 * @tc.steps: step1. var p1 = Promise.reject("Promise reject")
246 */
247 auto result = PromiseAlgorithm(thread, promise, paramMsg1.GetTaggedValue(), AlgorithmType::REJECT);
248 JSHandle<JSPromise> promise1(thread, result);
249 EXPECT_EQ(promise1->GetPromiseState(), PromiseState::REJECTED);
250 EXPECT_EQ(JSTaggedValue::SameValue(promise1->GetPromiseResult(), paramMsg1.GetTaggedValue()), true);
251
252 // promise1 Enter Reject() as a parameter.
253 /**
254 * @tc.steps: step2. var p2 = Promise.resolve(p1)
255 */
256 auto result1 = PromiseAlgorithm(thread, promise, promise1.GetTaggedValue(), AlgorithmType::RESOLVE);
257 JSHandle<JSPromise> promise2(thread, result1);
258 EXPECT_EQ(*promise1, *promise2);
259 EXPECT_EQ(promise2->GetPromiseState(), PromiseState::REJECTED);
260 EXPECT_EQ(JSTaggedValue::SameValue(promise2->GetPromiseResult(), paramMsg1.GetTaggedValue()), true);
261 }
262
263 /*
264 * @tc.name: Race1
265 * @tc.desc: The race method receives an array.
266 * @tc.type: FUNC
267 */
HWTEST_F_L0(BuiltinsPromiseTest, Race1)268 HWTEST_F_L0(BuiltinsPromiseTest, Race1)
269 {
270 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
271
272 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
273 JSHandle<JSTaggedValue> paramMsg1(thread, JSTaggedValue(12345));
274
275 /**
276 * @tc.steps: step1. var p1 = Promise.reject(12345)
277 */
278 auto result1 = PromiseAlgorithm(thread, promise, paramMsg1.GetTaggedValue(), AlgorithmType::REJECT);
279 JSHandle<JSPromise> rejectPromise(thread, result1);
280 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
281 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(12345)), true);
282
283 /**
284 * @tc.steps: step2. var p2 = Promise.resolve(6789)
285 */
286 JSHandle<JSTaggedValue> paramMsg2(thread, JSTaggedValue(6789));
287 auto result2 = PromiseAlgorithm(thread, promise, paramMsg2.GetTaggedValue(), AlgorithmType::RESOLVE);
288 JSHandle<JSPromise> resolvePromise(thread, result2);
289 EXPECT_EQ(resolvePromise->GetPromiseState(), PromiseState::FULFILLED);
290 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise->GetPromiseResult(), JSTaggedValue(6789)), true);
291 /**
292 * @tc.steps: step3. Construct an array with two elements p1 and p2. array = [p1. p2]
293 */
294 JSHandle<JSObject> array(JSArray::ArrayCreate(thread, JSTaggedNumber(2)));
295 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>::Cast(rejectPromise));
296 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), desc);
297
298 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>::Cast(resolvePromise));
299 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), desc1);
300
301 /**
302 * @tc.steps: step4. var p3 = Promise.race([p1,p2]);
303 */
304 auto result4 = PromiseAlgorithm(thread, promise, array.GetTaggedValue(), AlgorithmType::RACE);
305 JSHandle<JSPromise> racePromise(thread, result4);
306 EXPECT_EQ(racePromise->GetPromiseState(), PromiseState::PENDING);
307 EXPECT_EQ(racePromise->GetPromiseResult().IsUndefined(), true);
308 }
309
310 /*
311 * @tc.name: Race2
312 * @tc.desc: The Race method receives an array, uses the Then method to save the task in the task queue, and outputs
313 * the execution result of the queue.
314 * @tc.type: FUNC
315 */
HWTEST_F_L0(BuiltinsPromiseTest, Race2)316 HWTEST_F_L0(BuiltinsPromiseTest, Race2)
317 {
318 ObjectFactory *factory = instance->GetFactory();
319 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
320
321 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
322 JSHandle<JSTaggedValue> paramMsg1(thread, JSTaggedValue(12345));
323 JSHandle<JSTaggedValue> paramMsg2(thread, JSTaggedValue(6789));
324
325 /**
326 * @tc.steps: step1. var p1 = Promise.reject(12345)
327 */
328 auto result1 = PromiseAlgorithm(thread, promise, paramMsg1.GetTaggedValue(), AlgorithmType::REJECT);
329 JSHandle<JSPromise> rejectPromise(thread, result1);
330 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
331 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(12345)), true);
332
333 /**
334 * @tc.steps: step2. var p2 = Promise.resolve(6789)
335 */
336 auto result2 = PromiseAlgorithm(thread, promise, paramMsg2.GetTaggedValue(), AlgorithmType::RESOLVE);
337 JSHandle<JSPromise> resolvePromise(thread, result2);
338 EXPECT_EQ(resolvePromise->GetPromiseState(), PromiseState::FULFILLED);
339 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise->GetPromiseResult(), JSTaggedValue(6789)), true);
340
341 /**
342 * @tc.steps: step3. Construct an array with two elements p1 and p2. array = [p1. p2]
343 */
344 JSHandle<JSObject> array(JSArray::ArrayCreate(thread, JSTaggedNumber(2)));
345 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>::Cast(rejectPromise));
346 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), desc);
347
348 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>::Cast(resolvePromise));
349 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), desc1);
350
351 /**
352 * @tc.steps: step4. var p3 = Promise.race([p1,p2]);
353 */
354 auto result3 = PromiseAlgorithm(thread, promise, array.GetTaggedValue(), AlgorithmType::RACE);
355 JSHandle<JSPromise> racePromise(thread, result3);
356 EXPECT_EQ(racePromise->GetPromiseState(), PromiseState::PENDING);
357 EXPECT_EQ(racePromise->GetPromiseResult().IsUndefined(), true);
358
359 /**
360 * @tc.steps: step5. p3.then((resolve)=>{print(resolve)}, (reject)=>{print(reject)})
361 */
362 JSHandle<JSFunction> raceThenOnRejected =
363 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseRaceThenOnRejectd));
364 auto thenResult = ThanAlgorithm(thread, racePromise, JSTaggedValue::Undefined(),
365 raceThenOnRejected.GetTaggedValue());
366 JSHandle<JSPromise> thenPromise(thread, thenResult);
367
368 EXPECT_EQ(thenPromise->GetPromiseState(), PromiseState::PENDING);
369 EXPECT_TRUE(thenPromise->GetPromiseResult().IsUndefined());
370
371 /**
372 * @tc.steps: step6. execute promise queue
373 */
374 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
375 if (!thread->HasPendingException()) {
376 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
377 }
378 }
379
380 /*
381 * @tc.name: All
382 * @tc.desc: The All method receives an array, uses the Then method to save the task in the task queue, and outputs the
383 * execution result of the queue.
384 * @tc.type: FUNC
385 */
HWTEST_F_L0(BuiltinsPromiseTest, All)386 HWTEST_F_L0(BuiltinsPromiseTest, All)
387 {
388 ObjectFactory *factory = instance->GetFactory();
389 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
390
391 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
392 JSHandle<JSTaggedValue> paramMsg1(thread, JSTaggedValue(111));
393 JSHandle<JSTaggedValue> paramMsg2(thread, JSTaggedValue(222));
394
395 /**
396 * @tc.steps: step1. var p1 = Promise.resolve(111)
397 */
398 auto result1 = PromiseAlgorithm(thread, promise, paramMsg1.GetTaggedValue(), AlgorithmType::RESOLVE);
399 JSHandle<JSPromise> resolvePromise1(thread, result1);
400 EXPECT_EQ(resolvePromise1->GetPromiseState(), PromiseState::FULFILLED);
401 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise1->GetPromiseResult(), JSTaggedValue(111)), true);
402
403 /**
404 * @tc.steps: step2. var p2 = Promise.resolve(222)
405 */
406 auto result2 = PromiseAlgorithm(thread, promise, paramMsg2.GetTaggedValue(), AlgorithmType::RESOLVE);
407 JSHandle<JSPromise> resolvePromise2(thread, result2);
408 EXPECT_EQ(resolvePromise2->GetPromiseState(), PromiseState::FULFILLED);
409 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise2->GetPromiseResult(), JSTaggedValue(222)), true);
410
411 /**
412 * @tc.steps: step3. Construct an array with two elements p1 and p2. array = [p1. p2]
413 */
414 JSHandle<JSObject> array(JSArray::ArrayCreate(thread, JSTaggedNumber(2)));
415 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>::Cast(resolvePromise1));
416 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), desc);
417
418 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>::Cast(resolvePromise2));
419 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), desc1);
420
421 /**
422 * @tc.steps: step4. var p3 = Promise.all([p1,p2]);
423 */
424 auto result4 = PromiseAlgorithm(thread, promise, array.GetTaggedValue(), AlgorithmType::ALL);
425 JSHandle<JSPromise> allPromise(thread, result4);
426 EXPECT_EQ(allPromise->GetPromiseState(), PromiseState::PENDING);
427 EXPECT_EQ(allPromise->GetPromiseResult().IsUndefined(), true);
428
429 /**
430 * @tc.steps: step5. p3.then((resolve)=>{print(resolve)}, (reject)=>{print(reject)});
431 */
432 JSHandle<JSFunction> nativeFuncRaceThenOnResolved =
433 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseAllThenOnResolved));
434 auto thenResult = ThanAlgorithm(thread, allPromise, nativeFuncRaceThenOnResolved.GetTaggedValue(),
435 nativeFuncRaceThenOnResolved.GetTaggedValue());
436 JSHandle<JSPromise> thenPromise(thread, thenResult);
437
438 EXPECT_EQ(thenPromise->GetPromiseState(), PromiseState::PENDING);
439 EXPECT_TRUE(thenPromise->GetPromiseResult().IsUndefined());
440
441 /**
442 * @tc.steps: step6. execute promise queue
443 */
444 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
445 if (!thread->HasPendingException()) {
446 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
447 }
448 }
449
450 /*
451 * @tc.name: Catch
452 * @tc.desc: test Catch() method
453 * @tc.type: FUNC
454 */
HWTEST_F_L0(BuiltinsPromiseTest, Catch)455 HWTEST_F_L0(BuiltinsPromiseTest, Catch)
456 {
457 auto env = instance->GetGlobalEnv();
458 auto factory = instance->GetFactory();
459
460 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
461 JSHandle<JSTaggedValue> paramMsg1(thread, JSTaggedValue(3));
462
463 /**
464 * @tc.steps: step1. var p1 = Promise.reject(3)
465 */
466 auto result = PromiseAlgorithm(thread, promise, paramMsg1.GetTaggedValue(), AlgorithmType::REJECT);
467 JSHandle<JSPromise> rejectPromise(thread, result);
468 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
469 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(3)), true);
470
471 /**
472 * @tc.steps: step2. p1 invokes catch()
473 */
474 JSHandle<JSFunction> testPromiseCatch = factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseCatch));
475 auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, rejectPromise.GetTaggedValue(), 6);
476 ecmaRuntimeCallInfo2->SetFunction(rejectPromise.GetTaggedValue());
477 ecmaRuntimeCallInfo2->SetThis(rejectPromise.GetTaggedValue());
478 ecmaRuntimeCallInfo2->SetCallArg(0, testPromiseCatch.GetTaggedValue());
479
480 [[maybe_unused]] auto prevCatch = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
481 JSTaggedValue catchResult = BuiltinsPromise::Catch(ecmaRuntimeCallInfo2);
482 JSHandle<JSPromise> catchPromise(thread, catchResult);
483
484 EXPECT_EQ(catchPromise->GetPromiseState(), PromiseState::PENDING);
485 EXPECT_EQ(catchPromise->GetPromiseResult().IsUndefined(), true);
486 TestHelper::TearDownFrame(thread, prevCatch);
487
488 /**
489 * @tc.steps: step3. execute promise queue
490 */
491 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
492 if (!thread->HasPendingException()) {
493 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
494 }
495 }
496
497 /*
498 * @tc.name: ThenResolve
499 * @tc.desc: Testing the Then() function with the Resolve() function
500 * @tc.type: FUNC
501 */
HWTEST_F_L0(BuiltinsPromiseTest, ThenResolve)502 HWTEST_F_L0(BuiltinsPromiseTest, ThenResolve)
503 {
504 auto env = instance->GetGlobalEnv();
505 auto factory = instance->GetFactory();
506
507 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
508 JSHandle<JSTaggedValue> paramMsg = JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("resolve"));
509
510 /**
511 * @tc.steps: step1. var p1 = Promise.resolve("resolve")
512 */
513 auto result = PromiseAlgorithm(thread, promise, paramMsg.GetTaggedValue(), AlgorithmType::RESOLVE);
514 JSHandle<JSPromise> resolvePromise(thread, result);
515 EXPECT_EQ(resolvePromise->GetPromiseState(), PromiseState::FULFILLED);
516 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise->GetPromiseResult(), paramMsg.GetTaggedValue()), true);
517
518 /**
519 * @tc.steps: step2. p1 invokes then()
520 */
521 JSHandle<JSFunction> testPromiseThenOnResolved =
522 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseThenOnResolved));
523 auto thenResult = ThanAlgorithm(thread, resolvePromise, testPromiseThenOnResolved.GetTaggedValue(),
524 JSTaggedValue::Undefined());
525 JSHandle<JSPromise> thenPromise(thread, thenResult);
526
527 EXPECT_EQ(thenPromise->GetPromiseState(), PromiseState::PENDING);
528 EXPECT_EQ(thenPromise->GetPromiseResult().IsUndefined(), true);
529
530 /**
531 * @tc.steps: step3. execute promise queue
532 */
533 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
534 if (!thread->HasPendingException()) {
535 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
536 }
537 }
538
539 /*
540 * @tc.name: ThenReject
541 * @tc.desc: Testing the Then() function with the Reject() function
542 * @tc.type: FUNC
543 */
HWTEST_F_L0(BuiltinsPromiseTest, ThenReject)544 HWTEST_F_L0(BuiltinsPromiseTest, ThenReject)
545 {
546 auto env = instance->GetGlobalEnv();
547 auto factory = instance->GetFactory();
548
549 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
550 JSHandle<JSTaggedValue> paramMsg = JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("reject"));
551
552 /**
553 * @tc.steps: step1. var p1 = Promise.Reject(5)
554 */
555 auto result = PromiseAlgorithm(thread, promise, paramMsg.GetTaggedValue(), AlgorithmType::REJECT);
556 JSHandle<JSPromise> rejectPromise(thread, result);
557 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
558 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), paramMsg.GetTaggedValue()), true);
559
560 /**
561 * @tc.steps: step1. p1 invokes then()
562 */
563 JSHandle<JSFunction> testPromiseThenOnRejected =
564 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseThenOnRejected));
565 auto thenResult = ThanAlgorithm(thread, rejectPromise, testPromiseThenOnRejected.GetTaggedValue(),
566 testPromiseThenOnRejected.GetTaggedValue());
567 JSHandle<JSPromise> thenPromise(thread, thenResult);
568 EXPECT_EQ(thenPromise->GetPromiseState(), PromiseState::PENDING);
569 EXPECT_EQ(thenPromise->GetPromiseResult().IsUndefined(), true);
570 /**
571 * @tc.steps: step3. execute promise queue
572 */
573 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
574 if (!thread->HasPendingException()) {
575 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
576 }
577 }
578 } // namespace panda::test
579