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