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