1 /*
2 * Copyright (c) 2023 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 <cstdint>
17 #include <fstream>
18 #include <memory>
19 #include <string>
20 #include <utility>
21
22 #include "gtest/gtest.h"
23
24 #include "ecmascript/napi/include/jsnapi.h"
25 #include "ecmascript/ohos/ohos_pkg_args.h"
26 #include "ecmascript/ohos/enable_aot_list_helper.h"
27 #include "ecmascript/ohos/tests/mock/mock_enable_aot_list_helper.h"
28 #include "ecmascript/platform/file.h"
29 #include "ecmascript/tests/test_helper.h"
30
31 using namespace panda;
32 using namespace panda::ecmascript;
33 using namespace panda::ecmascript::kungfu;
34
35 namespace panda::test {
36 class OhosTest : public testing::Test {
37 public:
SetUpTestCase()38 static void SetUpTestCase()
39 {
40 GTEST_LOG_(INFO) << "SetUpTestCase";
41 }
42
TearDownTestCase()43 static void TearDownTestCase()
44 {
45 GTEST_LOG_(INFO) << "TearDownCase";
46 }
47
SetUp()48 void SetUp() override
49 {
50 runtimeOptions_.SetPGOProfilerPath("");
51 runtimeOptions_.SetTargetCompilerMode("partial");
52 runtimeOptions_.SetAOTOutputFile("/data/app/el1/public/aot_compiler/ark_cache/com.ohos.test/arm64/phone");
53 runtimeOptions_.SetCompilerPkgJsonInfo(
54 BuildOhosPkgJson("/data/app/el1/100/aot_compiler/ark_profile/com.ohos.test"));
55 runtimeOptions_.SetCompilerFrameworkAbcPath("/etc/abc/framework");
56 runtimeOptions_.SetCompilerEnableExternalPkg(true);
57 runtimeOptions_.SetCompilerExternalPkgJsonInfo(BuildOhosExternalPkgJson());
58 vm_ = JSNApi::CreateEcmaVM(runtimeOptions_);
59 ASSERT(vm_ != nullptr);
60 vm_->GetJSThread()->ManagedCodeBegin();
61 }
62
TearDown()63 void TearDown() override
64 {
65 vm_->GetJSThread()->ManagedCodeEnd();
66 ohos::EnableAotJitListHelper::GetInstance()->Clear();
67 JSNApi::DestroyJSVM(vm_);
68 vm_ = nullptr;
69 }
70
BuildOhosExternalPkgJson()71 static std::string BuildOhosExternalPkgJson()
72 {
73 return "[" + BuildOhosPkgJson("", TEST_BUNDLE_NAME, "entry1") + ", " +
74 BuildOhosPkgJson("", TEST_BUNDLE_NAME, "entry2") + "]";
75 }
76
BuildOhosPkgJson(const std::string & pgoDir,const std::string & bundleName=TEST_BUNDLE_NAME,const std::string & moduleName="entry")77 static std::string BuildOhosPkgJson(const std::string &pgoDir, const std::string &bundleName = TEST_BUNDLE_NAME,
78 const std::string &moduleName = "entry")
79 {
80 std::string pkgJson;
81 pkgJson += R"({"bundleName": ")" + bundleName + "\"";
82 pkgJson += R"(,"moduleName": ")" + moduleName + "\"";
83 pkgJson += R"(,"pkgPath": "/data/app/el1/bundle/public/com.ohos.test/entry.hap","abcName": "ets/modules.abc")";
84 pkgJson += R"(,"abcOffset": "0x6bb3c","abcSize": "0x51adfc")";
85 if (!pgoDir.empty()) {
86 pkgJson += R"(,"pgoDir": ")" + pgoDir + "\"";
87 }
88 return pkgJson + "}";
89 }
90
91 protected:
92 static constexpr const char *TEST_BUNDLE_NAME = "com.ohos.test";
93 JSRuntimeOptions runtimeOptions_;
94 EcmaVM *vm_ {nullptr};
95 };
96
HWTEST_F_L0(OhosTest,AotWhiteListTest)97 HWTEST_F_L0(OhosTest, AotWhiteListTest)
98 {
99 const char *whiteListTestDir = "ohos-whiteList/";
100 const char *enableListName = "ohos-whiteList/app_aot_jit_enable_list.conf";
101 std::string bundleScope = "com.bundle.scope.test";
102 std::string bundleScope1 = "com.bundle.scope.test1";
103 std::string bundleScope2 = "com.bundle.scope.test2";
104 mkdir(whiteListTestDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
105 std::ofstream file(enableListName);
106 file << bundleScope << std::endl;
107 file << bundleScope1 << ":aot" << std::endl;
108 file << bundleScope2 << ":jit" << std::endl;
109
110 file.close();
111 auto helper = std::make_unique<ohos::EnableAotJitListHelper>(enableListName);
112 ASSERT_TRUE(helper->IsEnableAot(bundleScope));
113 ASSERT_TRUE(helper->IsEnableJit(bundleScope));
114 ASSERT_TRUE(helper->IsEnableAot(bundleScope1));
115 ASSERT_FALSE(helper->IsEnableJit(bundleScope1));
116 ASSERT_FALSE(helper->IsEnableAot(bundleScope2));
117 ASSERT_TRUE(helper->IsEnableJit(bundleScope2));
118 unlink(enableListName);
119 rmdir(whiteListTestDir);
120 }
121
HWTEST_F_L0(OhosTest,AotWhiteListPassBy)122 HWTEST_F_L0(OhosTest, AotWhiteListPassBy)
123 {
124 const char *enableListName = "ohos-AotWhiteListPassBy/app_aot_jit_enable_list.conf";
125 std::string bundleScope = "com.bundle.scope.test";
126
127 auto helper = std::make_unique<ohos::EnableAotJitListHelper>(enableListName);
128 ASSERT_FALSE(helper->IsEnableAot(bundleScope));
129 ASSERT_FALSE(helper->IsEnableJit(bundleScope));
130 }
131
HWTEST_F_L0(OhosTest,OhosPkgArgsParse)132 HWTEST_F_L0(OhosTest, OhosPkgArgsParse)
133 {
134 const char *pgoDir = "ohos-OhosPkgArgsParse";
135 std::string runtimeAp = std::string(pgoDir) + "/rt_entry.ap";
136 mkdir(pgoDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
137 std::ofstream file(runtimeAp);
138 file.close();
139
140 arg_list_t pandaFileNames {};
141 std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
142 PGOProfilerDecoder decoder;
143
144 runtimeOptions_.SetPGOProfilerPath(runtimeAp);
145 runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(""));
146
147 CompilationOptions cOptions(runtimeOptions_);
148 AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
149 OhosPkgArgs::ParseArgs(preProcessor, cOptions);
150
151 ASSERT_EQ(preProcessor.GetMainPkgArgs()->GetBundleName(), TEST_BUNDLE_NAME);
152 ASSERT_EQ(preProcessor.GetMainPkgArgs()->GetModuleName(), "entry");
153 ASSERT_EQ(preProcessor.GetMainPkgArgs()->GetPath(), "/data/app/el1/bundle/public/com.ohos.test/entry.hap");
154 ASSERT_EQ(preProcessor.GetMainPkgArgs()->GetSize(), 0x51adfc);
155 ASSERT_EQ(preProcessor.GetMainPkgArgs()->GetOffset(), 0x6bb3c);
156 ASSERT_EQ(preProcessor.GetMainPkgArgs()->GetPgoDir(), pgoDir);
157
158 ASSERT_EQ(preProcessor.GetPkgsArgs().size(), 3);
159
160 unlink(runtimeAp.c_str());
161 rmdir(pgoDir);
162 }
163
HWTEST_F_L0(OhosTest,OhosPkgArgsParsePgoDir)164 HWTEST_F_L0(OhosTest, OhosPkgArgsParsePgoDir)
165 {
166 arg_list_t pandaFileNames {};
167 std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
168 PGOProfilerDecoder decoder;
169 CompilationOptions cOptions(runtimeOptions_);
170 AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
171 OhosPkgArgs::ParseArgs(preProcessor, cOptions);
172
173 ASSERT_EQ(preProcessor.GetMainPkgArgs()->GetPgoDir(), "/data/app/el1/100/aot_compiler/ark_profile/com.ohos.test");
174 }
175
HWTEST_F_L0(OhosTest,UseBaselineApFromPgoDir)176 HWTEST_F_L0(OhosTest, UseBaselineApFromPgoDir)
177 {
178 const char *pgoDir = "ohos-UseBaselineApFromPgoDir";
179 std::string baselineAp = std::string(pgoDir) + "/entry.ap";
180 std::string runtimeAp = std::string(pgoDir) + "/rt_entry.ap";
181 std::string mergedAp = std::string(pgoDir) + "/merged_entry.ap";
182 mkdir(pgoDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
183 std::ofstream file(baselineAp);
184 file.close();
185 file.open(runtimeAp);
186 file.close();
187 // do not add to white list
188
189 arg_list_t pandaFileNames {};
190 std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
191 PGOProfilerDecoder decoder;
192 CompilationOptions cOptions(runtimeOptions_);
193 AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
194 runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(pgoDir));
195 // Input format is correct, but there is no available ap file for pgoDir, return success.
196 ASSERT_TRUE(preProcessor.HandleTargetCompilerMode(cOptions));
197
198 ASSERT_FALSE(cOptions.profilerIn_.empty());
199 unlink(runtimeAp.c_str());
200 unlink(baselineAp.c_str());
201 unlink(mergedAp.c_str());
202 rmdir(pgoDir);
203 }
204
HWTEST_F_L0(OhosTest,UseRuntimeApWhenOnlyRuntimeExits)205 HWTEST_F_L0(OhosTest, UseRuntimeApWhenOnlyRuntimeExits)
206 {
207 const char *pgoDir = "ohos-UseRuntimeApWhenOnlyRuntimeExits";
208 std::string baselineAp = std::string(pgoDir) + "/entry.ap";
209 std::string runtimeAp = std::string(pgoDir) + "/rt_entry.ap";
210 std::string mergedAp = std::string(pgoDir) + "/merged_entry.ap";
211 mkdir(pgoDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
212 std::ofstream file(baselineAp);
213 file.close();
214 file.open(runtimeAp);
215 file.close();
216
217 arg_list_t pandaFileNames {};
218 std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
219 PGOProfilerDecoder decoder;
220 CompilationOptions cOptions(runtimeOptions_);
221 AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
222 runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(pgoDir));
223 ASSERT_TRUE(FileExist(runtimeAp.c_str()));
224 ASSERT_TRUE(preProcessor.HandleTargetCompilerMode(cOptions));
225
226 ASSERT_EQ(cOptions.profilerIn_, mergedAp);
227 ASSERT_TRUE(FileExist(mergedAp.c_str()));
228 ASSERT_TRUE(FileExist(baselineAp.c_str()));
229 ASSERT_FALSE(FileExist(runtimeAp.c_str()));
230 unlink(runtimeAp.c_str());
231 unlink(baselineAp.c_str());
232 unlink(mergedAp.c_str());
233 rmdir(pgoDir);
234 }
235
HWTEST_F_L0(OhosTest,UseMergedApWhenOnlyMergedExist)236 HWTEST_F_L0(OhosTest, UseMergedApWhenOnlyMergedExist)
237 {
238 const char *pgoDir = "ohos-UseMergedApWhenOnlyMergedExist";
239 std::string baselineAp = std::string(pgoDir) + "/entry.ap";
240 std::string mergedAp = std::string(pgoDir) + "/merged_entry.ap";
241 mkdir(pgoDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
242 std::ofstream file(baselineAp);
243 file.close();
244 file.open(mergedAp);
245 file.close();
246
247 arg_list_t pandaFileNames {};
248 std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
249 PGOProfilerDecoder decoder;
250 CompilationOptions cOptions(runtimeOptions_);
251 AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
252 runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(pgoDir));
253 ASSERT_TRUE(preProcessor.HandleTargetCompilerMode(cOptions));
254
255 ASSERT_EQ(cOptions.profilerIn_, mergedAp);
256 ASSERT_TRUE(FileExist(mergedAp.c_str()));
257 ASSERT_TRUE(FileExist(baselineAp.c_str()));
258 unlink(baselineAp.c_str());
259 unlink(mergedAp.c_str());
260 rmdir(pgoDir);
261 }
262
HWTEST_F_L0(OhosTest,UseMergedApWhenBothRuntimeAndMergedExist)263 HWTEST_F_L0(OhosTest, UseMergedApWhenBothRuntimeAndMergedExist)
264 {
265 const char *pgoDir = "ohos-UseMergedApWhenBothRuntimeAndMergedExist";
266 std::string baselineAp = std::string(pgoDir) + "/entry.ap";
267 std::string runtimeAp = std::string(pgoDir) + "/rt_entry.ap";
268 std::string mergedAp = std::string(pgoDir) + "/merged_entry.ap";
269 mkdir(pgoDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
270 std::ofstream file(baselineAp);
271 file.close();
272 file.open(mergedAp);
273 file.close();
274 file.open(runtimeAp);
275 file.close();
276
277 arg_list_t pandaFileNames {};
278 std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
279 PGOProfilerDecoder decoder;
280 CompilationOptions cOptions(runtimeOptions_);
281 AotCompilerPreprocessor preProcessor(vm_, runtimeOptions_, pkgArgsMap, decoder, pandaFileNames);
282 runtimeOptions_.SetCompilerPkgJsonInfo(BuildOhosPkgJson(pgoDir));
283 ASSERT_TRUE(OhosPkgArgs::ParseArgs(preProcessor, cOptions));
284
285 ASSERT_EQ(cOptions.profilerIn_, mergedAp + ":" + runtimeAp);
286 ASSERT_TRUE(FileExist(mergedAp.c_str()));
287 ASSERT_TRUE(FileExist(baselineAp.c_str()));
288 unlink(baselineAp.c_str());
289 unlink(runtimeAp.c_str());
290 unlink(mergedAp.c_str());
291 rmdir(pgoDir);
292 }
293
HWTEST_F_L0(OhosTest,AotIsEnableArkProfileTrue)294 HWTEST_F_L0(OhosTest, AotIsEnableArkProfileTrue)
295 {
296 const char *whiteListTestDir = "ohos-whiteList/";
297 const char *enableListName = "ohos-whiteList/app_aot_jit_enable_list.conf";
298 std::string bundleScope = "com.bundle.scope.test";
299 std::string bundleScope1 = "com.bundle.scope.test1";
300 std::string bundleScope2 = "com.bundle.scope.test2";
301 mkdir(whiteListTestDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
302 ohos::EnableAotJitListHelper *helper = new MockEnableAotJitListHelper(enableListName);
303
304 ASSERT_TRUE(helper->IsEnableAot(bundleScope));
305 ASSERT_TRUE(helper->IsEnableAot(bundleScope1));
306 ASSERT_TRUE(helper->IsEnableAot(bundleScope2));
307
308 unlink(enableListName);
309 rmdir(whiteListTestDir);
310 }
311
HWTEST_F_L0(OhosTest,AotIsEnableArkProfileFalse)312 HWTEST_F_L0(OhosTest, AotIsEnableArkProfileFalse)
313 {
314 const char *whiteListTestDir = "ohos-whiteList/";
315 const char *enableListName = "ohos-whiteList/app_aot_jit_enable_list.conf";
316 std::string bundleScope = "com.bundle.scope.test";
317 std::string bundleScope1 = "com.bundle.scope.test1";
318 std::string bundleScope2 = "com.bundle.scope.test2";
319 mkdir(whiteListTestDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
320 std::ofstream file(enableListName);
321 file << bundleScope << std::endl;
322 file.close();
323 auto helper = std::make_unique<ohos::EnableAotJitListHelper>(enableListName);
324
325 ASSERT_TRUE(helper->IsEnableAot(bundleScope));
326 ASSERT_FALSE(helper->IsEnableAot(bundleScope1));
327 ASSERT_FALSE(helper->IsEnableAot(bundleScope2));
328
329 unlink(enableListName);
330 rmdir(whiteListTestDir);
331 }
332
333 } // namespace panda::test