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