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 testing::Test {
39 public:
SetUpTestCase()40 static void SetUpTestCase()
41 {
42 GTEST_LOG_(INFO) << "SetUpTestCase";
43 }
44
TearDownTestCase()45 static void TearDownTestCase()
46 {
47 GTEST_LOG_(INFO) << "TearDownCase";
48 }
49
SetUp()50 void SetUp() override
51 {
52 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
53 }
54
TearDown()55 void TearDown() override
56 {
57 TestHelper::DestroyEcmaVMWithScope(instance, scope);
58 }
59
60 EcmaVM *instance {nullptr};
61 EcmaHandleScope *scope {nullptr};
62 JSThread *thread {nullptr};
63 };
64
65 // native function for race2 then_on_rejected()
TestPromiseRaceThenOnRejectd(EcmaRuntimeCallInfo * argv)66 JSTaggedValue TestPromiseRaceThenOnRejectd(EcmaRuntimeCallInfo *argv)
67 {
68 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
69 // 12345 : test case
70 EXPECT_EQ(JSTaggedValue::SameValue(result.GetTaggedValue(), JSTaggedValue(12345)), true);
71 return JSTaggedValue::Undefined();
72 }
73
74 // native function for all then_on_resolved()
TestPromiseAllThenOnResolved(EcmaRuntimeCallInfo * argv)75 JSTaggedValue TestPromiseAllThenOnResolved(EcmaRuntimeCallInfo *argv)
76 {
77 JSHandle<JSTaggedValue> array = BuiltinsBase::GetCallArg(argv, 0);
78 JSHandle<JSObject> objectArray = JSHandle<JSObject>::Cast(array);
79 [[maybe_unused]] PropertyDescriptor desc(argv->GetThread());
80 [[maybe_unused]] bool result1 = JSObject::GetOwnProperty(
81 argv->GetThread(), objectArray, JSHandle<JSTaggedValue>(argv->GetThread(), JSTaggedValue(0)), desc);
82 EXPECT_TRUE(result1);
83 JSHandle<JSTaggedValue> value1 = desc.GetValue();
84 // 111 : test case
85 EXPECT_EQ(JSTaggedValue::SameValue(value1.GetTaggedValue(), JSTaggedValue(111)), true);
86 [[maybe_unused]] bool result2 = JSObject::GetOwnProperty(
87 argv->GetThread(), objectArray, JSHandle<JSTaggedValue>(argv->GetThread(), JSTaggedValue(1)), desc);
88 EXPECT_TRUE(result2);
89 JSHandle<JSTaggedValue> value2 = desc.GetValue();
90 // 222 : test case
91 EXPECT_EQ(JSTaggedValue::SameValue(value2.GetTaggedValue(), JSTaggedValue(222)), true);
92 return JSTaggedValue::Undefined();
93 }
94
95 // native function for catch catch_on_rejected()
TestPromiseCatch(EcmaRuntimeCallInfo * argv)96 JSTaggedValue TestPromiseCatch(EcmaRuntimeCallInfo *argv)
97 {
98 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
99 // 3 : test case
100 EXPECT_EQ(JSTaggedValue::SameValue(result.GetTaggedValue(), JSTaggedValue(3)), true);
101 return JSTaggedValue::Undefined();
102 }
103
104 // native function for then then_on_resolved()
TestPromiseThenOnResolved(EcmaRuntimeCallInfo * argv)105 JSTaggedValue TestPromiseThenOnResolved(EcmaRuntimeCallInfo *argv)
106 {
107 auto factory = argv->GetThread()->GetEcmaVM()->GetFactory();
108 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
109 auto expect = factory->NewFromASCII("resolve");
110 EXPECT_EQ(JSTaggedValue::SameValue(result.GetTaggedValue(), expect.GetTaggedValue()), true);
111 return JSTaggedValue::Undefined();
112 }
113
114 // native function for then then_on_rejected()
TestPromiseThenOnRejected(EcmaRuntimeCallInfo * argv)115 JSTaggedValue TestPromiseThenOnRejected(EcmaRuntimeCallInfo *argv)
116 {
117 auto factory = argv->GetThread()->GetEcmaVM()->GetFactory();
118 JSHandle<JSTaggedValue> result = BuiltinsBase::GetCallArg(argv, 0);
119 auto expect = factory->NewFromASCII("reject");
120 EXPECT_EQ(JSTaggedValue::SameValue(result.GetTaggedValue(), expect.GetTaggedValue()), true);
121 return JSTaggedValue::Undefined();
122 }
123
124 /*
125 * @tc.name: Reject1
126 * @tc.desc: The reject method receives a number.
127 * @tc.type: FUNC
128 */
HWTEST_F_L0(BuiltinsPromiseTest,Reject1)129 HWTEST_F_L0(BuiltinsPromiseTest, Reject1)
130 {
131 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
132
133 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
134 JSHandle<JSTaggedValue> paramMsg(thread, JSTaggedValue(3));
135
136 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
137 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
138 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
139 ecmaRuntimeCallInfo1->SetCallArg(0, paramMsg.GetTaggedValue());
140
141 /**
142 * @tc.steps: var p1 = Promise.reject(3).
143 */
144 [[maybe_unused]] auto prevReject = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
145 JSTaggedValue result = BuiltinsPromise::Reject(ecmaRuntimeCallInfo1);
146 JSHandle<JSPromise> rejectPromise(thread, result);
147 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
148 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(3)), true);
149 TestHelper::TearDownFrame(thread, prevReject);
150 }
151
152 /*
153 * @tc.name: Reject2
154 * @tc.desc: The reject method receives a promise object.
155 * @tc.type: FUNC
156 */
HWTEST_F_L0(BuiltinsPromiseTest,Reject2)157 HWTEST_F_L0(BuiltinsPromiseTest, Reject2)
158 {
159 ObjectFactory *factory = instance->GetFactory();
160 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
161
162 // constructor promise1
163 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
164 JSHandle<JSTaggedValue> paramMsg1 =
165 JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("Promise reject"));
166
167 /**
168 * @tc.steps: step1. var p1 = Promise.reject("Promise reject")
169 */
170 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, promise.GetTaggedValue(), 6);
171 ecmaRuntimeCallInfo->SetFunction(promise.GetTaggedValue());
172 ecmaRuntimeCallInfo->SetThis(promise.GetTaggedValue());
173 ecmaRuntimeCallInfo->SetCallArg(0, paramMsg1.GetTaggedValue());
174
175 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
176 JSTaggedValue result = BuiltinsPromise::Reject(ecmaRuntimeCallInfo);
177 JSHandle<JSPromise> promise1(thread, result);
178 EXPECT_EQ(promise1->GetPromiseState(), PromiseState::REJECTED);
179 EXPECT_EQ(JSTaggedValue::SameValue(promise1->GetPromiseResult(), paramMsg1.GetTaggedValue()), true);
180 TestHelper::TearDownFrame(thread, prev);
181
182 /**
183 * @tc.steps: step2. var p2 = Promise.reject(p1)
184 */
185 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, promise.GetTaggedValue(), 6);
186 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
187 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
188 ecmaRuntimeCallInfo1->SetCallArg(0, promise1.GetTaggedValue());
189 [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
190
191 JSTaggedValue result1 = BuiltinsPromise::Reject(ecmaRuntimeCallInfo1);
192 JSHandle<JSPromise> promise2(thread, result1);
193 EXPECT_NE(*promise1, *promise2);
194 EXPECT_EQ(promise2->GetPromiseState(), PromiseState::REJECTED);
195 EXPECT_EQ(
196 JSTaggedValue::SameValue(promise2->GetPromiseResult(), JSTaggedValue(promise1.GetTaggedValue().GetRawData())),
197 true);
198 TestHelper::TearDownFrame(thread, prev);
199 }
200
201 /*
202 * @tc.name: Resolve1
203 * @tc.desc: The resolve method receives a number.
204 * @tc.type: FUNC
205 */
HWTEST_F_L0(BuiltinsPromiseTest,Resolve1)206 HWTEST_F_L0(BuiltinsPromiseTest, Resolve1)
207 {
208 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
209
210 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
211 JSHandle<JSTaggedValue> paramMsg(thread, JSTaggedValue(5));
212
213 /**
214 * @tc.steps: step1. var p1 = Promise.resolve(12345)
215 */
216 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
217 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
218 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
219 ecmaRuntimeCallInfo1->SetCallArg(0, paramMsg.GetTaggedValue());
220
221 [[maybe_unused]] auto prevReject = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
222 JSTaggedValue result = BuiltinsPromise::Resolve(ecmaRuntimeCallInfo1);
223 JSHandle<JSPromise> rejectPromise(thread, result);
224 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::FULFILLED);
225 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(5)), true);
226 TestHelper::TearDownFrame(thread, prevReject);
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 ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, promise.GetTaggedValue(), 6);
248 ecmaRuntimeCallInfo->SetFunction(promise.GetTaggedValue());
249 ecmaRuntimeCallInfo->SetThis(promise.GetTaggedValue());
250 ecmaRuntimeCallInfo->SetCallArg(0, paramMsg1.GetTaggedValue());
251
252 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
253 JSTaggedValue result = BuiltinsPromise::Reject(ecmaRuntimeCallInfo);
254 JSHandle<JSPromise> promise1(thread, result);
255 EXPECT_EQ(promise1->GetPromiseState(), PromiseState::REJECTED);
256 EXPECT_EQ(JSTaggedValue::SameValue(promise1->GetPromiseResult(), paramMsg1.GetTaggedValue()), true);
257 TestHelper::TearDownFrame(thread, prev);
258
259 // promise1 Enter Reject() as a parameter.
260 /**
261 * @tc.steps: step2. var p2 = Promise.resolve(p1)
262 */
263 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, promise.GetTaggedValue(), 6);
264 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
265 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
266 ecmaRuntimeCallInfo1->SetCallArg(0, promise1.GetTaggedValue());
267 [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
268
269 JSTaggedValue result1 = BuiltinsPromise::Resolve(ecmaRuntimeCallInfo1);
270 JSHandle<JSPromise> promise2(thread, result1);
271 EXPECT_EQ(*promise1, *promise2);
272 EXPECT_EQ(promise2->GetPromiseState(), PromiseState::REJECTED);
273 EXPECT_EQ(JSTaggedValue::SameValue(promise2->GetPromiseResult(), paramMsg1.GetTaggedValue()), true);
274 TestHelper::TearDownFrame(thread, prev1);
275 }
276
277 /*
278 * @tc.name: Race1
279 * @tc.desc: The race method receives an array.
280 * @tc.type: FUNC
281 */
HWTEST_F_L0(BuiltinsPromiseTest,Race1)282 HWTEST_F_L0(BuiltinsPromiseTest, Race1)
283 {
284 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
285
286 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
287 JSHandle<JSTaggedValue> paramMsg1(thread, JSTaggedValue(12345));
288 JSHandle<JSTaggedValue> paramMsg2(thread, JSTaggedValue(6789));
289
290 /**
291 * @tc.steps: step1. var p1 = Promise.reject(12345)
292 */
293 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
294 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
295 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
296 ecmaRuntimeCallInfo1->SetCallArg(0, paramMsg1.GetTaggedValue());
297
298 [[maybe_unused]] auto prevReject = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
299 JSTaggedValue result1 = BuiltinsPromise::Reject(ecmaRuntimeCallInfo1);
300 JSHandle<JSPromise> rejectPromise(thread, result1);
301 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
302 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(12345)), true);
303 TestHelper::TearDownFrame(thread, prevReject);
304
305 /**
306 * @tc.steps: step2. var p2 = Promise.resolve(6789)
307 */
308 auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
309 ecmaRuntimeCallInfo2->SetFunction(promise.GetTaggedValue());
310 ecmaRuntimeCallInfo2->SetThis(promise.GetTaggedValue());
311 ecmaRuntimeCallInfo2->SetCallArg(0, paramMsg2.GetTaggedValue());
312
313 [[maybe_unused]] auto prevResolve = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
314 JSTaggedValue result2 = BuiltinsPromise::Resolve(ecmaRuntimeCallInfo2);
315 JSHandle<JSPromise> resolvePromise(thread, result2);
316 EXPECT_EQ(resolvePromise->GetPromiseState(), PromiseState::FULFILLED);
317 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise->GetPromiseResult(), JSTaggedValue(6789)), true);
318 TestHelper::TearDownFrame(thread, prevResolve);
319
320 /**
321 * @tc.steps: step3. Construct an array with two elements p1 and p2. array = [p1. p2]
322 */
323 JSHandle<JSObject> array(JSArray::ArrayCreate(thread, JSTaggedNumber(2)));
324 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>::Cast(rejectPromise));
325 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), desc);
326
327 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>::Cast(resolvePromise));
328 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), desc1);
329
330 /**
331 * @tc.steps: step4. var p3 = Promise.race([p1,p2]);
332 */
333 auto ecmaRuntimeCallInfo4 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
334 ecmaRuntimeCallInfo4->SetFunction(promise.GetTaggedValue());
335 ecmaRuntimeCallInfo4->SetThis(promise.GetTaggedValue());
336 ecmaRuntimeCallInfo4->SetCallArg(0, array.GetTaggedValue());
337
338 [[maybe_unused]] auto prev4 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo4);
339 JSTaggedValue result4 = BuiltinsPromise::Race(ecmaRuntimeCallInfo4);
340 JSHandle<JSPromise> racePromise(thread, result4);
341 EXPECT_EQ(racePromise->GetPromiseState(), PromiseState::PENDING);
342 EXPECT_EQ(racePromise->GetPromiseResult().IsUndefined(), true);
343 TestHelper::TearDownFrame(thread, prev4);
344 }
345
346 /*
347 * @tc.name: Race2
348 * @tc.desc: The Race method receives an array, uses the Then method to save the task in the task queue, and outputs
349 * the execution result of the queue.
350 * @tc.type: FUNC
351 */
HWTEST_F_L0(BuiltinsPromiseTest,Race2)352 HWTEST_F_L0(BuiltinsPromiseTest, Race2)
353 {
354 ObjectFactory *factory = instance->GetFactory();
355 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
356
357 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
358 JSHandle<JSTaggedValue> paramMsg1(thread, JSTaggedValue(12345));
359 JSHandle<JSTaggedValue> paramMsg2(thread, JSTaggedValue(6789));
360
361 /**
362 * @tc.steps: step1. var p1 = Promise.reject(12345)
363 */
364 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
365 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
366 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
367 ecmaRuntimeCallInfo1->SetCallArg(0, paramMsg1.GetTaggedValue());
368
369 [[maybe_unused]] auto prevReject = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
370 JSTaggedValue result1 = BuiltinsPromise::Reject(ecmaRuntimeCallInfo1);
371 JSHandle<JSPromise> rejectPromise(thread, result1);
372 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
373 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(12345)), true);
374 TestHelper::TearDownFrame(thread, prevReject);
375
376 /**
377 * @tc.steps: step2. var p2 = Promise.resolve(6789)
378 */
379 auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
380 ecmaRuntimeCallInfo2->SetFunction(promise.GetTaggedValue());
381 ecmaRuntimeCallInfo2->SetThis(promise.GetTaggedValue());
382 ecmaRuntimeCallInfo2->SetCallArg(0, paramMsg2.GetTaggedValue());
383
384 [[maybe_unused]] auto prevResolve = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
385 JSTaggedValue result2 = BuiltinsPromise::Resolve(ecmaRuntimeCallInfo2);
386 JSHandle<JSPromise> resolvePromise(thread, result2);
387 EXPECT_EQ(resolvePromise->GetPromiseState(), PromiseState::FULFILLED);
388 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise->GetPromiseResult(), JSTaggedValue(6789)), true);
389 TestHelper::TearDownFrame(thread, prevResolve);
390
391 /**
392 * @tc.steps: step3. Construct an array with two elements p1 and p2. array = [p1. p2]
393 */
394 JSHandle<JSObject> array(JSArray::ArrayCreate(thread, JSTaggedNumber(2)));
395 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>::Cast(rejectPromise));
396 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), desc);
397
398 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>::Cast(resolvePromise));
399 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), desc1);
400
401 /**
402 * @tc.steps: step4. var p3 = Promise.race([p1,p2]);
403 */
404 auto ecmaRuntimeCallInfo4 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
405 ecmaRuntimeCallInfo4->SetFunction(promise.GetTaggedValue());
406 ecmaRuntimeCallInfo4->SetThis(promise.GetTaggedValue());
407 ecmaRuntimeCallInfo4->SetCallArg(0, array.GetTaggedValue());
408
409 [[maybe_unused]] auto prev4 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo4);
410 JSTaggedValue result4 = BuiltinsPromise::Race(ecmaRuntimeCallInfo4);
411 JSHandle<JSPromise> racePromise(thread, result4);
412 EXPECT_EQ(racePromise->GetPromiseState(), PromiseState::PENDING);
413 EXPECT_EQ(racePromise->GetPromiseResult().IsUndefined(), true);
414 TestHelper::TearDownFrame(thread, prev4);
415
416 /**
417 * @tc.steps: step5. p3.then((resolve)=>{print(resolve)}, (reject)=>{print(reject)})
418 */
419 JSHandle<JSFunction> native_func_race_then_onrejected =
420 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseRaceThenOnRejectd));
421 auto ecmaRuntimeCallInfo5 = TestHelper::CreateEcmaRuntimeCallInfo(thread, racePromise.GetTaggedValue(), 8);
422 ecmaRuntimeCallInfo5->SetFunction(racePromise.GetTaggedValue());
423 ecmaRuntimeCallInfo5->SetThis(racePromise.GetTaggedValue());
424 ecmaRuntimeCallInfo5->SetCallArg(0, JSTaggedValue::Undefined());
425 ecmaRuntimeCallInfo5->SetCallArg(1, native_func_race_then_onrejected.GetTaggedValue());
426
427 [[maybe_unused]] auto prev5 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo5);
428 JSTaggedValue thenResult = BuiltinsPromise::Then(ecmaRuntimeCallInfo5);
429 JSHandle<JSPromise> thenPromise(thread, thenResult);
430
431 EXPECT_EQ(thenPromise->GetPromiseState(), PromiseState::PENDING);
432 EXPECT_TRUE(thenPromise->GetPromiseResult().IsUndefined());
433 TestHelper::TearDownFrame(thread, prev5);
434
435 /**
436 * @tc.steps: step6. execute promise queue
437 */
438 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
439 if (!thread->HasPendingException()) {
440 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
441 }
442 }
443
444 /*
445 * @tc.name: All
446 * @tc.desc: The All method receives an array, uses the Then method to save the task in the task queue, and outputs the
447 * execution result of the queue.
448 * @tc.type: FUNC
449 */
HWTEST_F_L0(BuiltinsPromiseTest,All)450 HWTEST_F_L0(BuiltinsPromiseTest, All)
451 {
452 ObjectFactory *factory = instance->GetFactory();
453 JSHandle<GlobalEnv> env = instance->GetGlobalEnv();
454
455 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
456 JSHandle<JSTaggedValue> paramMsg1(thread, JSTaggedValue(111));
457 JSHandle<JSTaggedValue> paramMsg2(thread, JSTaggedValue(222));
458
459 /**
460 * @tc.steps: step1. var p1 = Promise.resolve(111)
461 */
462 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
463 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
464 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
465 ecmaRuntimeCallInfo1->SetCallArg(0, paramMsg1.GetTaggedValue());
466
467 [[maybe_unused]] auto prevReject = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
468 JSTaggedValue result1 = BuiltinsPromise::Resolve(ecmaRuntimeCallInfo1);
469 JSHandle<JSPromise> resolvePromise1(thread, result1);
470 EXPECT_EQ(resolvePromise1->GetPromiseState(), PromiseState::FULFILLED);
471 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise1->GetPromiseResult(), JSTaggedValue(111)), true);
472 TestHelper::TearDownFrame(thread, prevReject);
473
474 /**
475 * @tc.steps: step2. var p2 = Promise.resolve(222)
476 */
477 auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
478 ecmaRuntimeCallInfo2->SetFunction(promise.GetTaggedValue());
479 ecmaRuntimeCallInfo2->SetThis(promise.GetTaggedValue());
480 ecmaRuntimeCallInfo2->SetCallArg(0, paramMsg2.GetTaggedValue());
481
482 [[maybe_unused]] auto prevResolve = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
483 JSTaggedValue result2 = BuiltinsPromise::Resolve(ecmaRuntimeCallInfo2);
484 JSHandle<JSPromise> resolvePromise2(thread, result2);
485 EXPECT_EQ(resolvePromise2->GetPromiseState(), PromiseState::FULFILLED);
486 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise2->GetPromiseResult(), JSTaggedValue(222)), true);
487 TestHelper::TearDownFrame(thread, prevResolve);
488
489 /**
490 * @tc.steps: step3. Construct an array with two elements p1 and p2. array = [p1. p2]
491 */
492 JSHandle<JSObject> array(JSArray::ArrayCreate(thread, JSTaggedNumber(2)));
493 PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>::Cast(resolvePromise1));
494 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)), desc);
495
496 PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>::Cast(resolvePromise2));
497 JSArray::DefineOwnProperty(thread, array, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), desc1);
498
499 /**
500 * @tc.steps: step4. var p3 = Promise.all([p1,p2]);
501 */
502 auto ecmaRuntimeCallInfo4 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
503 ecmaRuntimeCallInfo4->SetFunction(promise.GetTaggedValue());
504 ecmaRuntimeCallInfo4->SetThis(promise.GetTaggedValue());
505 ecmaRuntimeCallInfo4->SetCallArg(0, array.GetTaggedValue());
506
507 [[maybe_unused]] auto prev4 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo4);
508 JSTaggedValue result4 = BuiltinsPromise::All(ecmaRuntimeCallInfo4);
509 JSHandle<JSPromise> allPromise(thread, result4);
510 EXPECT_EQ(allPromise->GetPromiseState(), PromiseState::PENDING);
511 EXPECT_EQ(allPromise->GetPromiseResult().IsUndefined(), true);
512 TestHelper::TearDownFrame(thread, prev4);
513
514 /**
515 * @tc.steps: step5. p3.then((resolve)=>{print(resolve)}, (reject)=>{print(reject)});
516 */
517 JSHandle<JSFunction> nativeFuncRaceThenOnResolved =
518 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseAllThenOnResolved));
519 auto ecmaRuntimeCallInfo5 = TestHelper::CreateEcmaRuntimeCallInfo(thread, allPromise.GetTaggedValue(), 8);
520 ecmaRuntimeCallInfo5->SetFunction(allPromise.GetTaggedValue());
521 ecmaRuntimeCallInfo5->SetThis(allPromise.GetTaggedValue());
522 ecmaRuntimeCallInfo5->SetCallArg(0, nativeFuncRaceThenOnResolved.GetTaggedValue());
523 ecmaRuntimeCallInfo5->SetCallArg(1, nativeFuncRaceThenOnResolved.GetTaggedValue());
524
525 [[maybe_unused]] auto prev5 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo5);
526 JSTaggedValue thenResult = BuiltinsPromise::Then(ecmaRuntimeCallInfo5);
527 JSHandle<JSPromise> thenPromise(thread, thenResult);
528
529 EXPECT_EQ(thenPromise->GetPromiseState(), PromiseState::PENDING);
530 EXPECT_TRUE(thenPromise->GetPromiseResult().IsUndefined());
531 TestHelper::TearDownFrame(thread, prev5);
532
533 /**
534 * @tc.steps: step6. execute promise queue
535 */
536 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
537 if (!thread->HasPendingException()) {
538 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
539 }
540 }
541
542 /*
543 * @tc.name: Catch
544 * @tc.desc: test Catch() method
545 * @tc.type: FUNC
546 */
HWTEST_F_L0(BuiltinsPromiseTest,Catch)547 HWTEST_F_L0(BuiltinsPromiseTest, Catch)
548 {
549 auto env = instance->GetGlobalEnv();
550 auto factory = instance->GetFactory();
551
552 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
553 JSHandle<JSTaggedValue> paramMsg1(thread, JSTaggedValue(3));
554
555 /**
556 * @tc.steps: step1. var p1 = Promise.reject(3)
557 */
558 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
559 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
560 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
561 ecmaRuntimeCallInfo1->SetCallArg(0, paramMsg1.GetTaggedValue());
562
563 [[maybe_unused]] auto prevReject = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
564 JSTaggedValue result = BuiltinsPromise::Reject(ecmaRuntimeCallInfo1);
565 JSHandle<JSPromise> rejectPromise(thread, result);
566 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
567 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), JSTaggedValue(3)), true);
568 TestHelper::TearDownFrame(thread, prevReject);
569
570 /**
571 * @tc.steps: step2. p1 invokes catch()
572 */
573 JSHandle<JSFunction> testPromiseCatch = factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseCatch));
574 auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, rejectPromise.GetTaggedValue(), 6);
575 ecmaRuntimeCallInfo2->SetFunction(rejectPromise.GetTaggedValue());
576 ecmaRuntimeCallInfo2->SetThis(rejectPromise.GetTaggedValue());
577 ecmaRuntimeCallInfo2->SetCallArg(0, testPromiseCatch.GetTaggedValue());
578
579 [[maybe_unused]] auto prevCatch = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
580 JSTaggedValue catchResult = BuiltinsPromise::Catch(ecmaRuntimeCallInfo2);
581 JSHandle<JSPromise> catchPromise(thread, catchResult);
582
583 EXPECT_EQ(catchPromise->GetPromiseState(), PromiseState::PENDING);
584 EXPECT_EQ(catchPromise->GetPromiseResult().IsUndefined(), true);
585 TestHelper::TearDownFrame(thread, prevCatch);
586
587 /**
588 * @tc.steps: step3. execute promise queue
589 */
590 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
591 if (!thread->HasPendingException()) {
592 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
593 }
594 }
595
596 /*
597 * @tc.name: ThenResolve
598 * @tc.desc: Testing the Then() function with the Resolve() function
599 * @tc.type: FUNC
600 */
HWTEST_F_L0(BuiltinsPromiseTest,ThenResolve)601 HWTEST_F_L0(BuiltinsPromiseTest, ThenResolve)
602 {
603 auto env = instance->GetGlobalEnv();
604 auto factory = instance->GetFactory();
605
606 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
607 JSHandle<JSTaggedValue> paramMsg = JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("resolve"));
608
609 /**
610 * @tc.steps: step1. var p1 = Promise.resolve("resolve")
611 */
612 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
613 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
614 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
615 ecmaRuntimeCallInfo1->SetCallArg(0, paramMsg.GetTaggedValue());
616
617 [[maybe_unused]] auto prevReject = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
618 JSTaggedValue result = BuiltinsPromise::Resolve(ecmaRuntimeCallInfo1);
619 JSHandle<JSPromise> resolvePromise(thread, result);
620 EXPECT_EQ(resolvePromise->GetPromiseState(), PromiseState::FULFILLED);
621 EXPECT_EQ(JSTaggedValue::SameValue(resolvePromise->GetPromiseResult(), paramMsg.GetTaggedValue()), true);
622 TestHelper::TearDownFrame(thread, prevReject);
623
624 /**
625 * @tc.steps: step2. p1 invokes then()
626 */
627 JSHandle<JSFunction> testPromiseThenOnResolved =
628 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseThenOnResolved));
629 auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, resolvePromise.GetTaggedValue(), 8);
630 ecmaRuntimeCallInfo2->SetFunction(resolvePromise.GetTaggedValue());
631 ecmaRuntimeCallInfo2->SetThis(resolvePromise.GetTaggedValue());
632 ecmaRuntimeCallInfo2->SetCallArg(0, testPromiseThenOnResolved.GetTaggedValue());
633 ecmaRuntimeCallInfo2->SetCallArg(1, JSTaggedValue::Undefined());
634
635 [[maybe_unused]] auto prevThen = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
636 JSTaggedValue thenResult = BuiltinsPromise::Then(ecmaRuntimeCallInfo2);
637 JSHandle<JSPromise> thenPromise(thread, thenResult);
638
639 EXPECT_EQ(thenPromise->GetPromiseState(), PromiseState::PENDING);
640 EXPECT_EQ(thenPromise->GetPromiseResult().IsUndefined(), true);
641 TestHelper::TearDownFrame(thread, prevThen);
642
643 /**
644 * @tc.steps: step3. execute promise queue
645 */
646 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
647 if (!thread->HasPendingException()) {
648 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
649 }
650 }
651
652 /*
653 * @tc.name: ThenReject
654 * @tc.desc: Testing the Then() function with the Reject() function
655 * @tc.type: FUNC
656 */
HWTEST_F_L0(BuiltinsPromiseTest,ThenReject)657 HWTEST_F_L0(BuiltinsPromiseTest, ThenReject)
658 {
659 auto env = instance->GetGlobalEnv();
660 auto factory = instance->GetFactory();
661
662 JSHandle<JSFunction> promise = JSHandle<JSFunction>::Cast(env->GetPromiseFunction());
663 JSHandle<JSTaggedValue> paramMsg = JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("reject"));
664
665 /**
666 * @tc.steps: step1. var p1 = Promise.Reject(5)
667 */
668 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*promise), 6);
669 ecmaRuntimeCallInfo1->SetFunction(promise.GetTaggedValue());
670 ecmaRuntimeCallInfo1->SetThis(promise.GetTaggedValue());
671 ecmaRuntimeCallInfo1->SetCallArg(0, paramMsg.GetTaggedValue());
672
673 [[maybe_unused]] auto prevReject = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
674 JSTaggedValue result = BuiltinsPromise::Reject(ecmaRuntimeCallInfo1);
675 JSHandle<JSPromise> rejectPromise(thread, result);
676 EXPECT_EQ(rejectPromise->GetPromiseState(), PromiseState::REJECTED);
677 EXPECT_EQ(JSTaggedValue::SameValue(rejectPromise->GetPromiseResult(), paramMsg.GetTaggedValue()), true);
678 TestHelper::TearDownFrame(thread, prevReject);
679
680 /**
681 * @tc.steps: step1. p1 invokes then()
682 */
683 JSHandle<JSFunction> testPromiseThenOnRejected =
684 factory->NewJSFunction(env, reinterpret_cast<void *>(TestPromiseThenOnRejected));
685 auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, rejectPromise.GetTaggedValue(), 8);
686 ecmaRuntimeCallInfo2->SetFunction(rejectPromise.GetTaggedValue());
687 ecmaRuntimeCallInfo2->SetThis(rejectPromise.GetTaggedValue());
688 ecmaRuntimeCallInfo2->SetCallArg(0, testPromiseThenOnRejected.GetTaggedValue());
689 ecmaRuntimeCallInfo2->SetCallArg(1, testPromiseThenOnRejected.GetTaggedValue());
690
691 [[maybe_unused]] auto prevThen = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
692 JSTaggedValue thenResult = BuiltinsPromise::Then(ecmaRuntimeCallInfo2);
693 JSHandle<JSPromise> thenPromise(thread, thenResult);
694
695 EXPECT_EQ(thenPromise->GetPromiseState(), PromiseState::PENDING);
696 EXPECT_EQ(thenPromise->GetPromiseResult().IsUndefined(), true);
697 TestHelper::TearDownFrame(thread, prevThen);
698 /**
699 * @tc.steps: step3. execute promise queue
700 */
701 auto microJobQueue = instance->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue();
702 if (!thread->HasPendingException()) {
703 job::MicroJobQueue::ExecutePendingJob(thread, microJobQueue);
704 }
705 }
706 } // namespace panda::test
707