• 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 <regex>
17 
18 #include "ability_delegator_registry.h"
19 #include "hilog_wrapper.h"
20 #include "js_runtime_utils.h"
21 #include "runner_runtime/js_test_runner.h"
22 
23 extern const char _binary_delegator_mgmt_abc_start[];
24 extern const char _binary_delegator_mgmt_abc_end[];
25 namespace OHOS {
26 namespace RunnerRuntime {
27 namespace {
28 const std::string CAPITALTESTRUNNER = "/ets/TestRunner/";
29 const std::string LOWERCASETESTRUNNER = "/ets/testrunner/";
30 }  // namespace
31 
Create(const std::unique_ptr<Runtime> & runtime,const std::shared_ptr<AbilityDelegatorArgs> & args,const AppExecFwk::BundleInfo & bundleInfo,bool isFaJsModel)32 std::unique_ptr<TestRunner> JsTestRunner::Create(const std::unique_ptr<Runtime> &runtime,
33     const std::shared_ptr<AbilityDelegatorArgs> &args, const AppExecFwk::BundleInfo &bundleInfo, bool isFaJsModel)
34 {
35     if (!runtime) {
36         HILOG_ERROR("Invalid runtime");
37         return nullptr;
38     }
39 
40     if (!args) {
41         HILOG_ERROR("Invalid ability delegator args");
42         return nullptr;
43     }
44 
45     auto pTestRunner = new (std::nothrow) JsTestRunner(static_cast<JsRuntime &>(*runtime), args, bundleInfo,
46         isFaJsModel);
47     if (!pTestRunner) {
48         HILOG_ERROR("Failed to create test runner");
49         return nullptr;
50     }
51 
52     return std::unique_ptr<JsTestRunner>(pTestRunner);
53 }
54 
JsTestRunner(JsRuntime & jsRuntime,const std::shared_ptr<AbilityDelegatorArgs> & args,const AppExecFwk::BundleInfo & bundleInfo,bool isFaJsModel)55 JsTestRunner::JsTestRunner(
56     JsRuntime &jsRuntime, const std::shared_ptr<AbilityDelegatorArgs> &args, const AppExecFwk::BundleInfo &bundleInfo,
57     bool isFaJsModel)
58     : jsRuntime_(jsRuntime), isFaJsModel_(isFaJsModel)
59 {
60     std::string moduleName;
61     if (args) {
62         std::string srcPath;
63         if (bundleInfo.hapModuleInfos.back().isModuleJson) {
64             srcPath.append(args->GetTestModuleName());
65             if (args->GetTestRunnerClassName().find("/") == std::string::npos) {
66                 srcPath.append(LOWERCASETESTRUNNER);
67             }
68             moduleName = args->GetTestModuleName();
69         } else {
70             srcPath.append(args->GetTestPackageName());
71             srcPath.append("/assets/js/TestRunner/");
72             moduleName = args->GetTestPackageName();
73         }
74         srcPath.append(args->GetTestRunnerClassName());
75         srcPath.append(".abc");
76         srcPath_ = srcPath;
77     }
78     HILOG_DEBUG("JsTestRunner srcPath is %{public}s", srcPath_.c_str());
79 
80     if (!moduleName.empty()) {
81         for (auto hapModuleInfo : bundleInfo.hapModuleInfos) {
82             if ((hapModuleInfo.isModuleJson && hapModuleInfo.name == moduleName) ||
83                 hapModuleInfo.package == moduleName) {
84                 hapPath_ = hapModuleInfo.hapPath;
85                 break;
86             }
87         }
88     } else {
89         hapPath_ = bundleInfo.hapModuleInfos.back().hapPath;
90     }
91     HILOG_DEBUG("JsTestRunner hapPath is %{public}s", hapPath_.c_str());
92 
93     if (isFaJsModel) {
94         return;
95     }
96 
97     moduleName.append("::").append("TestRunner");
98     jsTestRunnerObj_ = jsRuntime_.LoadModule(moduleName, srcPath_, hapPath_,
99         bundleInfo.hapModuleInfos.back().compileMode == AppExecFwk::CompileMode::ES_MODULE);
100     if (!jsTestRunnerObj_ && srcPath_.find(LOWERCASETESTRUNNER) != std::string::npos) {
101         HILOG_DEBUG("Not found %{public}s , retry load capital address", srcPath_.c_str());
102         std::regex src_pattern(LOWERCASETESTRUNNER);
103         srcPath_ = std::regex_replace(srcPath_, src_pattern, CAPITALTESTRUNNER);
104         HILOG_DEBUG("Capital address is %{public}s", srcPath_.c_str());
105         jsTestRunnerObj_ = jsRuntime_.LoadModule(moduleName, srcPath_, hapPath_,
106             bundleInfo.hapModuleInfos.back().compileMode == AppExecFwk::CompileMode::ES_MODULE);
107     }
108 }
109 
110 JsTestRunner::~JsTestRunner() = default;
111 
Initialize()112 bool JsTestRunner::Initialize()
113 {
114     if (isFaJsModel_) {
115         if (!jsRuntime_.RunScript("/system/etc/strip.native.min.abc", "")) {
116             HILOG_ERROR("RunScript err");
117             return false;
118         }
119         std::vector<uint8_t> buffer((uint8_t*)_binary_delegator_mgmt_abc_start,
120             (uint8_t*)_binary_delegator_mgmt_abc_end);
121         auto mgmtResult = jsRuntime_.GetNativeEngine().RunBufferScript(buffer);
122         if (mgmtResult == nullptr) {
123             HILOG_ERROR("mgmtResult init error");
124             return false;
125         }
126         if (!jsRuntime_.RunSandboxScript(srcPath_, hapPath_)) {
127             HILOG_ERROR("RunScript srcPath_ err");
128             return false;
129         }
130         NativeEngine& engine = jsRuntime_.GetNativeEngine();
131         NativeObject* object = ConvertNativeValueTo<NativeObject>(engine.GetGlobal());
132         if (object == nullptr) {
133             HILOG_ERROR("Failed to get global object");
134             return false;
135         }
136         NativeValue* mainEntryFunc = object->GetProperty("___mainEntry___");
137         if (mainEntryFunc == nullptr) {
138             HILOG_ERROR("Failed to get mainEntryFunc");
139             return false;
140         }
141         NativeValue* value = engine.GetGlobal();
142         if (value == nullptr) {
143             HILOG_ERROR("Failed to get global");
144             return false;
145         }
146         engine.CallFunction(engine.GetGlobal(), mainEntryFunc, &value, 1);
147     }
148     return true;
149 }
150 
Prepare()151 void JsTestRunner::Prepare()
152 {
153     HILOG_INFO("Enter");
154     TestRunner::Prepare();
155     CallObjectMethod("onPrepare");
156     HILOG_INFO("End");
157 }
158 
Run()159 void JsTestRunner::Run()
160 {
161     HILOG_INFO("Enter");
162     TestRunner::Run();
163     CallObjectMethod("onRun");
164     HILOG_INFO("End");
165 }
166 
CallObjectMethod(const char * name,NativeValue * const * argv,size_t argc)167 void JsTestRunner::CallObjectMethod(const char *name, NativeValue *const *argv, size_t argc)
168 {
169     HILOG_INFO("JsTestRunner::CallObjectMethod(%{public}s)", name);
170     if (isFaJsModel_) {
171         NativeEngine& engine = jsRuntime_.GetNativeEngine();
172         NativeObject* global = ConvertNativeValueTo<NativeObject>(engine.GetGlobal());
173         if (global == nullptr) {
174             HILOG_ERROR("Failed to get global object");
175             return;
176         }
177 
178         NativeObject* exportObject = ConvertNativeValueTo<NativeObject>(global->GetProperty("exports"));
179         if (exportObject == nullptr) {
180             HILOG_ERROR("Failed to get exportObject");
181             return;
182         }
183 
184         NativeObject* defaultObject = ConvertNativeValueTo<NativeObject>(exportObject->GetProperty("default"));
185         if (defaultObject == nullptr) {
186             HILOG_ERROR("Failed to get defaultObject");
187             return;
188         }
189 
190         NativeValue* func = defaultObject->GetProperty(name);
191         if (func == nullptr || !func->IsCallable()) {
192             HILOG_ERROR("CallRequest func is %{public}s", func == nullptr ? "nullptr" : "not func");
193             return;
194         }
195         engine.CallFunction(engine.CreateUndefined(), func, argv, argc);
196         return;
197     }
198 
199     if (!jsTestRunnerObj_) {
200         HILOG_ERROR("Not found %{public}s", srcPath_.c_str());
201         ReportFinished("Not found " + srcPath_);
202         return;
203     }
204 
205     HandleScope handleScope(jsRuntime_);
206     auto &nativeEngine = jsRuntime_.GetNativeEngine();
207 
208     NativeValue *value = jsTestRunnerObj_->Get();
209     NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
210     if (obj == nullptr) {
211         HILOG_ERROR("Failed to get Test Runner object");
212         ReportFinished("Failed to get Test Runner object");
213         return;
214     }
215 
216     NativeValue *methodOnCreate = obj->GetProperty(name);
217     if (methodOnCreate == nullptr) {
218         HILOG_ERROR("Failed to get '%{public}s' from Test Runner object", name);
219         ReportStatus("Failed to get " + std::string(name) + " from Test Runner object");
220         return;
221     }
222     nativeEngine.CallFunction(value, methodOnCreate, argv, argc);
223 }
224 
ReportFinished(const std::string & msg)225 void JsTestRunner::ReportFinished(const std::string &msg)
226 {
227     HILOG_INFO("Enter");
228     auto delegator = AbilityDelegatorRegistry::GetAbilityDelegator();
229     if (!delegator) {
230         HILOG_ERROR("delegator is null");
231         return;
232     }
233 
234     delegator->FinishUserTest(msg, -1);
235 }
236 
ReportStatus(const std::string & msg)237 void JsTestRunner::ReportStatus(const std::string &msg)
238 {
239     HILOG_INFO("Enter");
240     auto delegator = AbilityDelegatorRegistry::GetAbilityDelegator();
241     if (!delegator) {
242         HILOG_ERROR("delegator is null");
243         return;
244     }
245 
246     delegator->Print(msg);
247 }
248 }  // namespace RunnerRuntime
249 }  // namespace OHOS
250