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