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