1 /*
2 * Copyright (c) 2025 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 #include <cstdarg>
16 #include <gtest/gtest.h>
17 #include <dlfcn.h>
18 #include <gtest/hwext/gtest-multithread.h>
19 #include <string>
20
21 #include "runtime.h"
22 #define private public
23 #include "ets_environment.h"
24 #undef private
25
26 using namespace testing;
27 using namespace testing::ext;
28 using namespace testing::mt;
29
30 namespace {
31 bool g_callbackModuleFlag;
32 }
33
34 namespace OHOS {
35 namespace EtsEnv {
36 const std::string TEST_ABILITY_NAME = "ContactsDataAbility";
37
38 class EtsEnvironmentTest : public testing::Test {
39 public:
40 static void SetUpTestCase();
41 static void TearDownTestCase();
42 void SetUp() override;
43 void TearDown() override;
44 };
45
SetUpTestCase()46 void EtsEnvironmentTest::SetUpTestCase() {}
47
TearDownTestCase()48 void EtsEnvironmentTest::TearDownTestCase() {}
49
SetUp()50 void EtsEnvironmentTest::SetUp() {}
51
TearDown()52 void EtsEnvironmentTest::TearDown() {}
53
54 namespace {
CallBackModuleFunc()55 void CallBackModuleFunc()
56 {
57 g_callbackModuleFlag = true;
58 }
59 } // namespace
60
61 /**
62 * @tc.name: LoadBootPathFile_0100
63 * @tc.desc: LoadBootPathFile.
64 * @tc.type: FUNC
65 */
66 HWTEST_F(EtsEnvironmentTest, LoadBootPathFile_0100, TestSize.Level0)
67 {
68 auto etsEnv = std::make_shared<ETSEnvironment>();
69 ASSERT_NE(etsEnv, nullptr);
70 std::string str = "LoadBootPathFile";
71 bool bVal = etsEnv->LoadBootPathFile(str);
72 EXPECT_EQ(bVal, true);
73 }
74 /**
75 * @tc.name: LoadRuntimeApis_0100
76 * @tc.desc: LoadRuntimeApis.
77 * @tc.type: FUNC
78 */
79 HWTEST_F(EtsEnvironmentTest, LoadRuntimeApis_0100, TestSize.Level0)
80 {
81 auto etsEnv = std::make_shared<ETSEnvironment>();
82 ASSERT_NE(etsEnv, nullptr);
83 bool bVal = etsEnv->LoadRuntimeApis();
84 EXPECT_EQ(bVal, true);
85 }
86
87 /**
88 * @tc.name: GetBuildId_0100
89 * @tc.desc: Test GetBuildId with stack containing non-parseable lines.
90 * @tc.type: FUNC
91 */
92 HWTEST_F(EtsEnvironmentTest, GetBuildId_0100, TestSize.Level0)
93 {
94 auto etsEnv = std::make_shared<ETSEnvironment>();
95 ASSERT_NE(etsEnv, nullptr);
96 std::string stack = "NonParseableLineWithoutSpace\n"
97 "#00 pc 000000000001a0b8 /system/lib64/libutils.so\n"
98 "AnotherLineWithoutSpace\n";
99 std::string result = etsEnv->GetBuildId(stack);
100 EXPECT_FALSE(result.empty());
101 EXPECT_NE(result.find("/system/lib64/libutils.so"), std::string::npos);
102 EXPECT_EQ(result.find("NonParseableLineWithoutSpace"), std::string::npos);
103 EXPECT_EQ(result.find("AnotherLineWithoutSpace"), std::string::npos);
104 size_t expectedLines = 1;
105 size_t resultLines = std::count(result.begin(), result.end(), '\n');
106 EXPECT_EQ(resultLines, expectedLines);
107 }
108
109 /**
110 * @tc.name: GetBuildId_0200
111 * @tc.desc: Test GetBuildId with empty input.
112 * @tc.type: FUNC
113 */
114 HWTEST_F(EtsEnvironmentTest, GetBuildId_0200, TestSize.Level0)
115 {
116 auto etsEnv = std::make_shared<ETSEnvironment>();
117 ASSERT_NE(etsEnv, nullptr);
118 std::string stack = "";
119 std::string result = etsEnv->GetBuildId(stack);
120 EXPECT_TRUE(result.empty());
121 }
122
123 /**
124 * @tc.name: GetBuildId_0300
125 * @tc.desc: Test GetBuildId with stack containing only newlines.
126 * @tc.type: FUNC
127 */
128 HWTEST_F(EtsEnvironmentTest, GetBuildId_0300, TestSize.Level0)
129 {
130 auto etsEnv = std::make_shared<ETSEnvironment>();
131 ASSERT_NE(etsEnv, nullptr);
132 std::string stack = "\n\n\n";
133 std::string result = etsEnv->GetBuildId(stack);
134 EXPECT_TRUE(result.empty());
135 }
136
137 /**
138 * @tc.name: RegisterUncaughtExceptionHandler_0100
139 * @tc.desc: Test basic registration and triggering of uncaught exception handler.
140 * @tc.type: FUNC
141 */
142 HWTEST_F(EtsEnvironmentTest, RegisterUncaughtExceptionHandler_0100, TestSize.Level0)
143 {
144 auto etsEnv = std::make_shared<ETSEnvironment>();
145 ASSERT_NE(etsEnv, nullptr);
146 g_callbackModuleFlag = false;
147 ETSUncaughtExceptionInfo handlerInfo;
__anon07dbeeb90302(const std::string& summary, const ETSErrorObject& errorObj) 148 handlerInfo.uncaughtTask = [](const std::string& summary, const ETSErrorObject& errorObj) {
149 g_callbackModuleFlag = true;
150 };
151 etsEnv->RegisterUncaughtExceptionHandler(handlerInfo);
152 ETSErrorObject errorObj;
153 errorObj.name = "TestError";
154 errorObj.message = "Test error message";
155 errorObj.stack = "Test stack trace";
156 etsEnv->uncaughtExceptionInfo_.uncaughtTask("Test summary", errorObj);
157 EXPECT_TRUE(g_callbackModuleFlag);
158 }
159
160 /**
161 * @tc.name: GetAniEnv_0100
162 * @tc.desc: GetAniEnv.
163 * @tc.type: FUNC
164 */
165 HWTEST_F(EtsEnvironmentTest, GetAniEnv_0100, TestSize.Level0)
166 {
167 auto etsEnv = std::make_shared<ETSEnvironment>();
168 ETSEnvironment::VMEntry vMEntryOld = etsEnv->vmEntry_;
169 ETSEnvironment::VMEntry vmEntry;
170 vmEntry.aniEnv_ = nullptr;
171 etsEnv->vmEntry_ = vmEntry;
172 auto result = etsEnv->GetAniEnv();
173 EXPECT_EQ(result, nullptr);
174 etsEnv->vmEntry_ = vMEntryOld;
175 }
176
177 /**
178 * @tc.name: LoadSymbolCreateVM_0100
179 * @tc.desc: Test LoadSymbolCreateVM when dlsym returns nullptr.
180 * @tc.type: FUNC
181 */
182 HWTEST_F(EtsEnvironmentTest, LoadSymbolCreateVM_0100, TestSize.Level1)
183 {
184 auto etsEnv = std::make_shared<ETSEnvironment>();
185 ASSERT_NE(etsEnv, nullptr);
186 void* handle = dlopen(nullptr, RTLD_LAZY);
187 ASSERT_NE(handle, nullptr);
188 ETSRuntimeAPI apis = {};
189 bool result = etsEnv->LoadSymbolCreateVM(handle, apis);
190 dlclose(handle);
191 EXPECT_TRUE(result);
192 EXPECT_NE(apis.ANI_CreateVM, nullptr);
193 }
194
195 /**
196 * @tc.name: LoadSymbolCreateVM_0200
197 * @tc.desc: Test LoadSymbolCreateVM returns false when symbol is not found.
198 * @tc.type: FUNC
199 */
200 HWTEST_F(EtsEnvironmentTest, LoadSymbolCreateVM_0200, TestSize.Level0)
201 {
202 auto etsEnv = std::make_shared<ETSEnvironment>();
203 ASSERT_NE(etsEnv, nullptr);
204 void* invalidHandle = reinterpret_cast<void*>(0x1);
205 ETSRuntimeAPI apis = {};
206 bool result = etsEnv->LoadSymbolCreateVM(invalidHandle, apis);
207 EXPECT_FALSE(result);
208 EXPECT_EQ(apis.ANI_CreateVM, nullptr);
209 }
210
211 /**
212 * @tc.name: LoadSymbolANIGetCreatedVMs_0100
213 * @tc.desc: Test LoadSymbolANIGetCreatedVMs when symbol is not found.
214 * @tc.type: FUNC
215 */
216 HWTEST_F(EtsEnvironmentTest, LoadSymbolANIGetCreatedVMs_0100, TestSize.Level1)
217 {
218 auto etsEnv = std::make_shared<ETSEnvironment>();
219 ASSERT_NE(etsEnv, nullptr);
220 void* handle = dlopen(nullptr, RTLD_LAZY);
221 ASSERT_NE(handle, nullptr);
222 ETSRuntimeAPI apis = {};
223 bool result = etsEnv->LoadSymbolANIGetCreatedVMs(handle, apis);
224 dlclose(handle);
225 EXPECT_TRUE(result);
226 EXPECT_NE(apis.ANI_GetCreatedVMs, nullptr);
227 }
228
229 /**
230 * @tc.name: LoadSymbolANIGetCreatedVMs_0200
231 * @tc.desc: Test LoadSymbolANIGetCreatedVMs returns false when symbol is not found.
232 * @tc.type: FUNC
233 */
234 HWTEST_F(EtsEnvironmentTest, LoadSymbolANIGetCreatedVMs_0200, TestSize.Level0)
235 {
236 auto etsEnv = std::make_shared<ETSEnvironment>();
237 ASSERT_NE(etsEnv, nullptr);
238 void* invalidHandle = reinterpret_cast<void*>(0x1);
239 ETSRuntimeAPI apis = {};
240 bool result = etsEnv->LoadSymbolANIGetCreatedVMs(invalidHandle, apis);
241 EXPECT_FALSE(result);
242 EXPECT_EQ(apis.ANI_GetCreatedVMs, nullptr);
243 }
244
245 /**
246 * @tc.name: Initialize_0100
247 * @tc.desc: Test Initialize can be called without crash.
248 * @tc.type: FUNC
249 */
250 HWTEST_F(EtsEnvironmentTest, Initialize_0100, TestSize.Level0)
251 {
252 auto etsEnv = std::make_shared<ETSEnvironment>();
253 ASSERT_NE(etsEnv, nullptr);
254 bool result = etsEnv->Initialize();
255 EXPECT_FALSE(result);
256 }
257
258 /**
259 * @tc.name: HandleUncaughtError_0100
260 * @tc.desc: Test HandleUncaughtError can be called without crash.
261 * @tc.type: FUNC
262 */
263 HWTEST_F(EtsEnvironmentTest, HandleUncaughtError_0100, TestSize.Level1)
264 {
265 auto etsEnv = std::make_shared<ETSEnvironment>();
266 ASSERT_NE(etsEnv, nullptr);
267 bool result = etsEnv->HandleUncaughtError();
268 EXPECT_FALSE(result);
269 }
270
271 /**
272 * @tc.name: LoadAbcLinker_0100
273 * @tc.desc: LoadAbcLinker returns false when env is nullptr.
274 * @tc.type: FUNC
275 */
276 HWTEST_F(EtsEnvironmentTest, LoadAbcLinker_0100, TestSize.Level0)
277 {
278 auto etsEnv = std::make_shared<ETSEnvironment>();
279 ASSERT_NE(etsEnv, nullptr);
280 ani_class cls = nullptr;
281 ani_object obj = nullptr;
282 bool result = etsEnv->LoadAbcLinker(nullptr, "testModule", cls, obj);
283 EXPECT_FALSE(result);
284 }
285
286 /**
287 * @tc.name: PreloadModule_0100
288 * @tc.desc: PreloadModule returns false when env is nullptr.
289 * @tc.type: FUNC
290 */
291 HWTEST_F(EtsEnvironmentTest, PreloadModule_0100, TestSize.Level0)
292 {
293 auto etsEnv = std::make_shared<ETSEnvironment>();
294 ASSERT_NE(etsEnv, nullptr);
295 bool result = etsEnv->PreloadModule("testModule");
296 EXPECT_FALSE(result);
297 }
298
299 /**
300 * @tc.name: LoadModule_0100
301 * @tc.desc: LoadModule returns false when env is nullptr.
302 * @tc.type: FUNC
303 */
304 HWTEST_F(EtsEnvironmentTest, LoadModule_0100, TestSize.Level0)
305 {
306 auto etsEnv = std::make_shared<ETSEnvironment>();
307 ASSERT_NE(etsEnv, nullptr);
308 void *cls = nullptr;
309 void *obj = nullptr;
310 void *ref = nullptr;
311 bool result = etsEnv->LoadModule("testModule", "testModule", cls, obj, ref);
312 EXPECT_FALSE(result);
313 }
314
315 /**
316 * @tc.name: FinishPreload_0100
317 * @tc.desc: Sts environment FinishPreload.
318 * @tc.type: FUNC
319 */
320 HWTEST_F(EtsEnvironmentTest, FinishPreload_0100, TestSize.Level0)
321 {
322 auto etsEnv = std::make_shared<ETSEnvironment>();
323 ASSERT_NE(etsEnv, nullptr);
324 auto result = etsEnv->FinishPreload();
325 EXPECT_FALSE(result);
326 }
327
328 /**
329 * @tc.name: PostFork_0100
330 * @tc.desc: Sts environment PostFork.
331 * @tc.type: FUNC
332 */
333 HWTEST_F(EtsEnvironmentTest, PostFork_0100, TestSize.Level0)
334 {
335 auto etsEnv = std::make_shared<ETSEnvironment>();
336 ASSERT_NE(etsEnv, nullptr);
337 void *napiEnv = nullptr;
338 std::string aotPath = "aotPath";
339 auto result = etsEnv->PostFork(napiEnv, aotPath);
340 EXPECT_FALSE(result);
341 }
342
343 /**
344 * @tc.name: PreloadSystemClass_0100
345 * @tc.desc: Sts environment PreloadSystemClass.
346 * @tc.type: FUNC
347 */
348 HWTEST_F(EtsEnvironmentTest, PreloadSystemClass_0100, TestSize.Level0)
349 {
350 auto etsEnv = std::make_shared<ETSEnvironment>();
351 ASSERT_NE(etsEnv, nullptr);
352 std::string className = "className";
353 auto result = etsEnv->PreloadSystemClass(className.c_str());
354 EXPECT_FALSE(result);
355 }
356 } // namespace StsEnv
357 } // namespace OHOS