• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 <gtest/gtest.h>
17 #include <singleton.h>
18 #include <uv.h>
19 #include "ability_context.h"
20 #include "ability_context_impl.h"
21 #include "ability_business_error.h"
22 #include "errors.h"
23 #include "hilog_wrapper.h"
24 #define private public
25 #define protected public
26 #include "js_ability_context.h"
27 #undef private
28 #undef protected
29 #include "js_runtime_utils.h"
30 #include "native_engine/impl/ark/ark_native_engine.h"
31 #include "native_engine/impl/ark/ark_native_deferred.h"
32 #include "native_engine/native_engine.h"
33 #include "js_runtime_lite.h"
34 #include "napi_common_want.h"
35 
36 #include "mock_parse_requestcode.h"
37 
38 using namespace testing;
39 using namespace testing::ext;
40 using namespace OHOS::AAFwk;
41 using namespace OHOS::AbilityRuntime;
42 
43 namespace OHOS {
44 namespace AbilityRuntime {
45 
46 constexpr size_t ARGC_ZERO = 0;
47 constexpr size_t ARGC_ONE = 1;
48 constexpr size_t ARGC_TWO = 2;
49 
50 const int USLEEPTIME = 100000;
51 
52 napi_env env_ = nullptr;
53 panda::ecmascript::EcmaVM* vm_ = nullptr;
54 
55 class MockDeferred : public NativeDeferred {
56 public:
Resolve(napi_value data)57     void Resolve(napi_value data) override
58     {
59         resolved_ = true;
60         if (nref_ != nullptr) {
61             napi_delete_reference(env_, nref_);
62             nref_ = nullptr;
63         }
64         if (data != nullptr) {
65             napi_create_reference(env_, data, 1, &nref_);
66         }
67     }
68 
Reject(napi_value reason)69     void Reject(napi_value reason) override
70     {
71         resolved_ = false;
72     }
73 
74 public:
GetLastResolveStatus()75     static bool GetLastResolveStatus() { return resolved_; }
GetLastResolveValue()76     static napi_ref GetLastResolveValue() { return nref_; }
Clear()77     static void Clear()
78     {
79         if (nref_) {
80             delete (reinterpret_cast<NativeReference*>(nref_));
81             nref_ = nullptr;
82         }
83     }
84     static bool resolved_;
85     static napi_ref nref_;
86 };
87 bool MockDeferred::resolved_ = false;
88 napi_ref MockDeferred::nref_ = nullptr;
89 
90 class MockArkNativeEngine : public ArkNativeEngine {
91 public:
MockArkNativeEngine(EcmaVM * vm,void * jsEngine,bool isLimitedWorker=false)92     MockArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker = false)
93         :ArkNativeEngine(vm, jsEngine, isLimitedWorker)
94     {}
95 
CreatePromise(NativeDeferred ** deferred)96     napi_value CreatePromise(NativeDeferred** deferred) override
97     {
98         napi_value ret = ArkNativeEngine::CreatePromise(deferred);
99         *deferred = new (std::nothrow) MockDeferred;
100         return ret;
101     }
102 };
103 
104 class MockAbilityContextImpl : public AbilityContextImpl {
105 public:
ConnectUIServiceExtensionAbility(const AAFwk::Want & want,const sptr<AbilityConnectCallback> & connectCallback)106     virtual ErrCode ConnectUIServiceExtensionAbility(const AAFwk::Want &want,
107         const sptr<AbilityConnectCallback> &connectCallback) override
108     {
109         callback_ = connectCallback;
110         GTEST_LOG_(INFO) << "ConnectAbility, ret " << connectRet_;
111         return connectRet_;
112     }
113 
DisconnectAbility(const AAFwk::Want & want,const sptr<AbilityConnectCallback> & connectCallback,int32_t accountId=-1)114     void DisconnectAbility(const AAFwk::Want &want, const sptr<AbilityConnectCallback> &connectCallback,
115         int32_t accountId = -1) override
116     {}
117 public:
DoneConnect(int status)118     static void DoneConnect(int status)
119     {
120         GTEST_LOG_(INFO) << "DoneConnect " << status;
121         AppExecFwk::ElementName element;
122         sptr<IRemoteObject> remoteObject;
123         callback_->OnAbilityConnectDone(element, remoteObject, 0);
124     }
DoneDisconnect(int status)125     static void DoneDisconnect(int status)
126     {
127         GTEST_LOG_(INFO) << "DoneDisconnect " << status;
128         AppExecFwk::ElementName element;
129         callback_->OnAbilityDisconnectDone(element, 0);
130     }
SetConnectResult(ErrCode code)131     void SetConnectResult(ErrCode code) { connectRet_ = code; }
132 protected:
133     static sptr<AbilityConnectCallback> callback_;
134     ErrCode connectRet_ = ERR_OK;
135 };
136 
137 sptr<AbilityConnectCallback> MockAbilityContextImpl::callback_;
138 
139 class AbilityContextTest : public testing::Test {
140 public:
141     void SetUp();
142     void TearDown();
143     static void SetUpTestCase(void);
144     static void TearDownTestCase(void);
145 
RunNowait(uv_loop_t * loop)146     void RunNowait(uv_loop_t* loop)
147     {
148         usleep(USLEEPTIME);
149         uv_run(loop, UV_RUN_NOWAIT);
150     }
151     void Connect(napi_value* argv, int32_t argc);
152     void Disconnect(napi_value* argv, int32_t argc);
153 public:
154     std::shared_ptr<JsAbilityContext> jsAbilityContext_;
155     std::shared_ptr<MockAbilityContextImpl> abilityContextImpl_;
156 };
157 
SetUpTestCase()158 void AbilityContextTest::SetUpTestCase()
159 {
160     GTEST_LOG_(INFO) << "SetUpTestCase";
161     panda::RuntimeOption option;
162     option.SetGcType(panda::RuntimeOption::GC_TYPE::GEN_GC);
163     const int64_t poolSize = 0x1000000;
164     option.SetGcPoolSize(poolSize);
165     option.SetLogLevel(panda::RuntimeOption::LOG_LEVEL::ERROR);
166     option.SetDebuggerLibraryPath("");
167     vm_ = panda::JSNApi::CreateJSVM(option);
168     if (vm_ == nullptr) {
169         GTEST_LOG_(INFO) << "Create vm failed.";
170         return;
171     }
172     env_ = reinterpret_cast<napi_env>(new (std::nothrow) MockArkNativeEngine(vm_, nullptr));
173 }
174 
TearDownTestCase()175 void AbilityContextTest::TearDownTestCase()
176 {
177     GTEST_LOG_(INFO) << "TearDownTestCase";
178     MockArkNativeEngine* engine = reinterpret_cast<MockArkNativeEngine*>(env_);
179     delete engine;
180     engine = nullptr;
181     if (vm_ != nullptr) {
182         JSNApi::DestroyJSVM(vm_);
183         vm_ = nullptr;
184     }
185 }
186 
SetUp()187 void AbilityContextTest::SetUp()
188 {
189     GTEST_LOG_(INFO) << "AbilityContextTest::SetUp";
190     abilityContextImpl_ = std::make_shared<MockAbilityContextImpl>();
191     if (abilityContextImpl_ == nullptr) {
192         GTEST_LOG_(INFO) << "abilityContextImpl is nullptr.";
193         return;
194     }
195     jsAbilityContext_ = std::make_shared<JsAbilityContext>(abilityContextImpl_);
196 }
197 
TearDown()198 void AbilityContextTest::TearDown()
199 {
200     GTEST_LOG_(INFO) << "AbilityContextTest::TearDown " << (void*)this;
201     MockDeferred::Clear();
202     abilityContextImpl_.reset();
203     jsAbilityContext_.reset();
204 }
205 
Connect(napi_value * argv,int32_t argc)206 void AbilityContextTest::Connect(napi_value* argv, int32_t argc)
207 {
208     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0100 start";
209     auto func = [](napi_env env, napi_callback_info info) -> napi_value {
210         JsAbilityContext::ConnectUIServiceExtension(env, info);
211         napi_value result = nullptr;
212         napi_get_undefined(env, &result);
213         return result;
214     };
215 
216     HandleScope handleScope(env_);
217     napi_value recv = nullptr;
218     napi_create_object(env_, &recv);
219     napi_status wrapret = napi_wrap(env_, recv, jsAbilityContext_.get(),
220         [](napi_env env, void* data, void* hint) {}, nullptr, nullptr);
221     EXPECT_EQ(wrapret, napi_ok);
222 
223     napi_value funcValue = nullptr;
224     napi_create_function(env_, "testFunc", NAPI_AUTO_LENGTH, func, nullptr, &funcValue);
225 
226     napi_value funcResultValue = nullptr;
227     napi_call_function(env_, recv, funcValue, argc, argv, &funcResultValue);
228 }
229 
Disconnect(napi_value * argv,int32_t argc)230 void AbilityContextTest::Disconnect(napi_value* argv, int32_t argc)
231 {
232     auto func = [](napi_env env, napi_callback_info info) -> napi_value {
233         JsAbilityContext::DisconnectUIServiceExtension(env, info);
234         napi_value result = nullptr;
235         napi_get_undefined(env, &result);
236         return result;
237     };
238     HandleScope handleScope(env_);
239     napi_value recv = nullptr;
240     napi_create_object(env_, &recv);
241     napi_status wrapret = napi_wrap(env_, recv, jsAbilityContext_.get(), [](napi_env env, void* data, void* hint) {},
242         nullptr, nullptr);
243     EXPECT_EQ(wrapret, napi_ok);
244 
245     napi_value funcResultValue = nullptr;
246     napi_value funcValue = nullptr;
247     napi_create_function(env_, "disconnectFunc", NAPI_AUTO_LENGTH, func, nullptr, &funcValue);
248     napi_call_function(env_, recv, funcValue, argc, argv, &funcResultValue);
249 }
250 
251 HWTEST_F(AbilityContextTest, AbilityRuntime_AbilityContext_0100, TestSize.Level1)
252 {
253     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0100 start";
254     HandleScope handleScope(env_);
255     TryCatch tryCatch(env_);
256     napi_value argv[] = { };
257     Connect(argv, ARGC_ZERO);
258     EXPECT_TRUE(tryCatch.HasCaught());
259     tryCatch.ClearException();
260     ArkNativeEngine* engine = (ArkNativeEngine*)env_;
261     if (!engine->lastException_.IsEmpty()) {
262         engine->lastException_.Empty();
263     }
264 
265     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0100 end";
266 }
267 
268 HWTEST_F(AbilityContextTest, AbilityRuntime_AbilityContext_0101, TestSize.Level1)
269 {
270     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0101 start";
271     HandleScope handleScope(env_);
272     TryCatch tryCatch(env_);
273     napi_value undef = nullptr;
274     napi_get_undefined(env_, &undef);
275     napi_value argv[] = { undef };
276     Connect(argv, ARGC_ONE);
277     EXPECT_TRUE(tryCatch.HasCaught());
278     tryCatch.ClearException();
279     ArkNativeEngine* engine = (ArkNativeEngine*)env_;
280     if (!engine->lastException_.IsEmpty()) {
281         engine->lastException_.Empty();
282     }
283 
284     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0101 end";
285 }
286 
287 HWTEST_F(AbilityContextTest, AbilityRuntime_AbilityContext_0102, TestSize.Level1)
288 {
289     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0102 start";
290     HandleScope handleScope(env_);
291     TryCatch tryCatch(env_);
292     AAFwk::Want want;
293     napi_value jswant = AppExecFwk::CreateJsWant(env_, want);
294     napi_value argv[] = { jswant };
295     Connect(argv, ARGC_ONE);
296     EXPECT_TRUE(tryCatch.HasCaught());
297     tryCatch.ClearException();
298     ArkNativeEngine* engine = (ArkNativeEngine*)env_;
299     if (!engine->lastException_.IsEmpty()) {
300         engine->lastException_.Empty();
301     }
302 
303     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0102 end";
304 }
305 
306 HWTEST_F(AbilityContextTest, AbilityRuntime_AbilityContext_0103, TestSize.Level1)
307 {
308     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0103 start";
309     HandleScope handleScope(env_);
310     TryCatch tryCatch(env_);
311     AAFwk::Want want;
312     napi_value jswant = AppExecFwk::CreateJsWant(env_, want);
313     napi_value callbackObject = nullptr;
314     napi_create_object(env_, &callbackObject);
315     napi_value argv[] = { jswant, callbackObject};
316     Connect(argv, ARGC_TWO);
317     EXPECT_FALSE(tryCatch.HasCaught());
318 
319     ArkNativeEngine* engine = (ArkNativeEngine*)env_;
320     uv_loop_t* loop = engine->GetUVLoop();
321     RunNowait(loop);
322     MockAbilityContextImpl::DoneConnect(ERR_OK);
323     RunNowait(loop);
324 
325     EXPECT_TRUE(MockDeferred::GetLastResolveStatus());
326     napi_ref nref = MockDeferred::GetLastResolveValue();
327     EXPECT_NE(nref, nullptr);
328     napi_value proxy = (reinterpret_cast<NativeReference*>(nref))->GetNapiValue();
329     napi_value argv2[] = { proxy };
330     Disconnect(argv2, ARGC_ONE);
331     RunNowait(loop);
332 
333     MockAbilityContextImpl::DoneDisconnect(0);
334     RunNowait(loop);
335     abilityContextImpl_->SetConnectResult(ERR_OK);
336     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0103 end";
337 }
338 
339 HWTEST_F(AbilityContextTest, AbilityRuntime_AbilityContext_0104, TestSize.Level1)
340 {
341     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0104 start";
342     HandleScope handleScope(env_);
343     TryCatch tryCatch(env_);
344     napi_value argv[] = {};
345     Disconnect(argv, ARGC_ZERO);
346     EXPECT_TRUE(tryCatch.HasCaught());
347     tryCatch.ClearException();
348     ArkNativeEngine* engine = (ArkNativeEngine*)env_;
349     if (!engine->lastException_.IsEmpty()) {
350         engine->lastException_.Empty();
351     }
352     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0104 end";
353 }
354 
355 HWTEST_F(AbilityContextTest, AbilityRuntime_AbilityContext_0105, TestSize.Level1)
356 {
357     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0105 start";
358     HandleScope handleScope(env_);
359     TryCatch tryCatch(env_);
360     napi_value proxy = nullptr;
361     napi_create_object(env_, &proxy);
362     napi_value argv[] = {proxy};
363     Disconnect(argv, ARGC_ONE);
364     EXPECT_TRUE(tryCatch.HasCaught());
365     tryCatch.ClearException();
366     ArkNativeEngine* engine = (ArkNativeEngine*)env_;
367     if (!engine->lastException_.IsEmpty()) {
368         engine->lastException_.Empty();
369     }
370     GTEST_LOG_(INFO) << "AbilityRuntime_AbilityContext_0105 end";
371 }
372 
373 HWTEST_F(AbilityContextTest, AbilityRuntime_AbilityContext_RequestCodeFromStringToInt64_0100, TestSize.Level1)
374 {
375     // requestCode is too long
376     std::string requestCodeStr1 = "1000000000000001";
377     auto requestCode = RequestCodeFromStringToInt64(requestCodeStr1);
378     EXPECT_EQ(requestCode, 0);
379 
380     // requestCode not match
381     std::string requestCodeStr2 = "001000";
382     requestCode = RequestCodeFromStringToInt64(requestCodeStr2);
383     EXPECT_EQ(requestCode, 0);
384 
385     std::string requestCodeStr3 = "aaa100";
386     requestCode = RequestCodeFromStringToInt64(requestCodeStr3);
387     EXPECT_EQ(requestCode, 0);
388 
389     std::string requestCodeStr4 = "100aaa";
390     requestCode = RequestCodeFromStringToInt64(requestCodeStr4);
391     EXPECT_EQ(requestCode, 0);
392 
393     std::string requestCodeStr5 = "-1";
394     requestCode = RequestCodeFromStringToInt64(requestCodeStr5);
395     EXPECT_EQ(requestCode, 0);
396 
397     // requestCode is too large
398     std::string requestCodeStr6 = "562949953421312";
399     requestCode = RequestCodeFromStringToInt64(requestCodeStr6);
400     EXPECT_EQ(requestCode, 0);
401 
402     // requestCode is valid
403     std::string requestCodeStr7 = "562949953421311";
404     requestCode = RequestCodeFromStringToInt64(requestCodeStr7);
405     EXPECT_EQ(requestCode, 562949953421311);
406 
407     std::string requestCodeStr8 = "0";
408     requestCode = RequestCodeFromStringToInt64(requestCodeStr8);
409     EXPECT_EQ(requestCode, 0);
410 
411     std::string requestCodeStr9 = "1";
412     requestCode = RequestCodeFromStringToInt64(requestCodeStr9);
413     EXPECT_EQ(requestCode, 1);
414 }
415 
416 HWTEST_F(AbilityContextTest, AbilityRuntime_AbilityContext_StartUIServiceExtension_0100, TestSize.Level1)
417 {
418     napi_env env{nullptr};
419     napi_callback_info info{nullptr};
420     jsAbilityContext_->StartUIServiceExtension(env, info);
421     EXPECT_EQ(info, nullptr);
422 }
423 
424 HWTEST_F(AbilityContextTest, AbilityRuntime_AbilityContext_OnStartUIServiceExtension_0100, TestSize.Level1)
425 {
426     OHOS::AbilityRuntime::Runtime::Options options;
427     std::shared_ptr<OHOS::JsEnv::JsEnvironment> jsEnv = nullptr;
428     auto err = JsRuntimeLite::GetInstance().CreateJsEnv(options, jsEnv);
429     EXPECT_EQ(err, napi_status::napi_ok);
430     napi_env env = reinterpret_cast<napi_env>(jsEnv->GetNativeEngine());
431 
432     NapiCallbackInfo info{1};
433     AAFwk::Want want;
434     info.argv[0] = OHOS::AppExecFwk::WrapWant(env, want);
435     jsAbilityContext_->OnStartUIServiceExtension(env, info);
436 
437     JsRuntimeLite::GetInstance().RemoveJsEnv(reinterpret_cast<napi_env>(jsEnv->GetNativeEngine()));
438 }
439 
440 }  // namespace AAFwk
441 }  // namespace OHOS