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