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
16 #include <gtest/gtest.h>
17 #include "appexecfwk_errors.h"
18 #define private public
19 #include "app_running_status_module.h"
20 #include "appmgr/app_running_status_stub.h"
21 #undef private
22 #include "hilog_tag_wrapper.h"
23
24 using namespace testing;
25 using namespace testing::ext;
26
27 namespace OHOS {
28 namespace AbilityRuntime {
29
30 class MockAppRunningStatusListener : public AppRunningStatusStub {
31 public:
NotifyAppRunningStatus(const std::string & bundle,int32_t uid,RunningStatus runningStatus)32 void NotifyAppRunningStatus(const std::string &bundle, int32_t uid, RunningStatus runningStatus) override
33 {
34 bundle_ = bundle;
35 uid_ = uid;
36 runningStatus_ = runningStatus;
37 notifyCount_++;
38 }
39
40 std::string bundle_;
41 int32_t uid_ = 0;
42 RunningStatus runningStatus_ = RunningStatus::APP_RUNNING_STOP;
43 int32_t notifyCount_ = 0;
44 };
45
46 class AppRunningStatusModuleTest : public testing::Test {
47 public:
48 void SetUp() override;
49 void TearDown() override;
50
51 protected:
52 std::shared_ptr<AppRunningStatusModule> appRunningStatusModule_ = nullptr;
53 };
54
SetUp()55 void AppRunningStatusModuleTest::SetUp()
56 {
57 appRunningStatusModule_ = std::make_shared<AppRunningStatusModule>();
58 }
59
TearDown()60 void AppRunningStatusModuleTest::TearDown()
61 {
62 appRunningStatusModule_ = nullptr;
63 }
64
65 /**
66 * @tc.number: AppRunningStatusModuleTest_RegisterListener_0100
67 * @tc.desc: Test RegisterListener with null listener
68 * @tc.type: FUNC
69 * @tc.function: RegisterListener
70 * @tc.subfunction: NA
71 * @tc.envConditions: NA
72 */
73 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_RegisterListener_0100, TestSize.Level0)
74 {
75 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_RegisterListener_0100 start.");
76 sptr<AppRunningStatusListenerInterface> listener;
77 auto ret = appRunningStatusModule_->RegisterListener(listener);
78 EXPECT_EQ(ret, ERR_INVALID_OPERATION);
79 }
80
81 /**
82 * @tc.number: AppRunningStatusModuleTest_RegisterListener_0200
83 * @tc.desc: Test RegisterListener with valid listener
84 * @tc.type: FUNC
85 * @tc.function: RegisterListener
86 * @tc.subfunction: NA
87 * @tc.envConditions: NA
88 */
89 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_RegisterListener_0200, TestSize.Level0)
90 {
91 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_RegisterListener_0200 start.");
92 sptr<MockAppRunningStatusListener> listener = new MockAppRunningStatusListener();
93 auto ret = appRunningStatusModule_->RegisterListener(listener);
94 EXPECT_EQ(ret, ERR_OK);
95 }
96
97 /**
98 * @tc.number: AppRunningStatusModuleTest_RegisterListener_0300
99 * @tc.desc: Test RegisterListener with same listener twice
100 * @tc.type: FUNC
101 * @tc.function: RegisterListener
102 * @tc.subfunction: NA
103 * @tc.envConditions: NA
104 */
105 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_RegisterListener_0300, TestSize.Level0)
106 {
107 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_RegisterListener_0300 start.");
108 sptr<MockAppRunningStatusListener> listener = new MockAppRunningStatusListener();
109 auto ret = appRunningStatusModule_->RegisterListener(listener);
110 EXPECT_EQ(ret, ERR_OK);
111 ret = appRunningStatusModule_->RegisterListener(listener);
112 EXPECT_EQ(ret, ERR_OK);
113 }
114
115 /**
116 * @tc.number: AppRunningStatusModuleTest_UnregisterListener_0100
117 * @tc.desc: Test UnregisterListener with null listener
118 * @tc.type: FUNC
119 * @tc.function: UnregisterListener
120 * @tc.subfunction: NA
121 * @tc.envConditions: NA
122 */
123 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_UnregisterListener_0100, TestSize.Level0)
124 {
125 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_UnregisterListener_0100 start.");
126 sptr<AppRunningStatusListenerInterface> listener;
127 auto ret = appRunningStatusModule_->UnregisterListener(listener);
128 EXPECT_EQ(ret, ERR_INVALID_VALUE);
129 }
130
131 /**
132 * @tc.number: AppRunningStatusModuleTest_UnregisterListener_0200
133 * @tc.desc: Test UnregisterListener with unregistered listener
134 * @tc.type: FUNC
135 * @tc.function: UnregisterListener
136 * @tc.subfunction: NA
137 * @tc.envConditions: NA
138 */
139 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_UnregisterListener_0200, TestSize.Level0)
140 {
141 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_UnregisterListener_0200 start.");
142 sptr<MockAppRunningStatusListener> listener = new MockAppRunningStatusListener();
143 auto ret = appRunningStatusModule_->UnregisterListener(listener);
144 EXPECT_EQ(ret, ERR_INVALID_OPERATION);
145 }
146
147 /**
148 * @tc.number: AppRunningStatusModuleTest_UnregisterListener_0300
149 * @tc.desc: Test UnregisterListener with registered listener
150 * @tc.type: FUNC
151 * @tc.function: UnregisterListener
152 * @tc.subfunction: NA
153 * @tc.envConditions: NA
154 */
155 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_UnregisterListener_0300, TestSize.Level0)
156 {
157 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_UnregisterListener_0300 start.");
158 sptr<MockAppRunningStatusListener> listener = new MockAppRunningStatusListener();
159
160 auto ret = appRunningStatusModule_->RegisterListener(listener);
161 EXPECT_EQ(ret, ERR_OK);
162 ret = appRunningStatusModule_->UnregisterListener(listener);
163 EXPECT_EQ(ret, ERR_OK);
164 }
165
166 /**
167 * @tc.number: AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0100
168 * @tc.desc: Test NotifyAppRunningStatusEvent with no listeners
169 * @tc.type: FUNC
170 * @tc.function: NotifyAppRunningStatusEvent
171 * @tc.subfunction: NA
172 * @tc.envConditions: NA
173 */
174 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0100, TestSize.Level0)
175 {
176 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0100 start.");
177 std::string bundleName = "com.test.bundle";
178 int32_t uid = 1000;
179 RunningStatus runningStatus = RunningStatus::APP_RUNNING_START;
180
181 // Verify no listeners are registered initially
182 {
183 std::lock_guard<std::mutex> lock(appRunningStatusModule_->listenerMutex_);
184 EXPECT_TRUE(appRunningStatusModule_->listeners_.empty());
185 }
186
187 // Call NotifyAppRunningStatusEvent with no listeners - should complete without errors
188 appRunningStatusModule_->NotifyAppRunningStatusEvent(bundleName, uid, runningStatus);
189
190 // Verify listeners container remains empty after the call
191 {
192 std::lock_guard<std::mutex> lock(appRunningStatusModule_->listenerMutex_);
193 EXPECT_TRUE(appRunningStatusModule_->listeners_.empty());
194 }
195 }
196
197 /**
198 * @tc.number: AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0200
199 * @tc.desc: Test NotifyAppRunningStatusEvent with registered listener
200 * @tc.type: FUNC
201 * @tc.function: NotifyAppRunningStatusEvent
202 * @tc.subfunction: NA
203 * @tc.envConditions: NA
204 */
205 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0200, TestSize.Level0)
206 {
207 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0200 start.");
208 sptr<MockAppRunningStatusListener> listener = new MockAppRunningStatusListener();
209
210 // Register listener
211 auto ret = appRunningStatusModule_->RegisterListener(listener);
212 EXPECT_EQ(ret, ERR_OK);
213
214 std::string bundleName = "com.test.bundle";
215 int32_t uid = 1000;
216 RunningStatus runningStatus = RunningStatus::APP_RUNNING_START;
217
218 // Notify event
219 appRunningStatusModule_->NotifyAppRunningStatusEvent(bundleName, uid, runningStatus);
220
221 // Check if listener was notified
222 EXPECT_EQ(listener->notifyCount_, 1);
223 EXPECT_EQ(listener->bundle_, bundleName);
224 EXPECT_EQ(listener->uid_, uid);
225 EXPECT_EQ(listener->runningStatus_, runningStatus);
226 }
227
228 /**
229 * @tc.number: AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0300
230 * @tc.desc: Test NotifyAppRunningStatusEvent with multiple listeners
231 * @tc.type: FUNC
232 * @tc.function: NotifyAppRunningStatusEvent
233 * @tc.subfunction: NA
234 * @tc.envConditions: NA
235 */
236 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0300, TestSize.Level0)
237 {
238 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0300 start.");
239 sptr<MockAppRunningStatusListener> listener1 = new MockAppRunningStatusListener();
240 sptr<MockAppRunningStatusListener> listener2 = new MockAppRunningStatusListener();
241
242 // Register listeners
243 auto ret = appRunningStatusModule_->RegisterListener(listener1);
244 EXPECT_EQ(ret, ERR_OK);
245 ret = appRunningStatusModule_->RegisterListener(listener2);
246 EXPECT_EQ(ret, ERR_OK);
247
248 std::string bundleName = "com.test.bundle";
249 int32_t uid = 1000;
250 RunningStatus runningStatus = RunningStatus::APP_RUNNING_STOP;
251
252 // Notify event
253 appRunningStatusModule_->NotifyAppRunningStatusEvent(bundleName, uid, runningStatus);
254
255 // Check if both listeners were notified
256 EXPECT_EQ(listener1->notifyCount_, 1);
257 EXPECT_EQ(listener1->bundle_, bundleName);
258 EXPECT_EQ(listener1->uid_, uid);
259 EXPECT_EQ(listener1->runningStatus_, runningStatus);
260
261 EXPECT_EQ(listener2->notifyCount_, 1);
262 EXPECT_EQ(listener2->bundle_, bundleName);
263 EXPECT_EQ(listener2->uid_, uid);
264 EXPECT_EQ(listener2->runningStatus_, runningStatus);
265 }
266
267 /**
268 * @tc.number: AppRunningStatusModuleTest_RemoveListenerAndDeathRecipient_0100
269 * @tc.desc: Test RemoveListenerAndDeathRecipient with null remote object
270 * @tc.type: FUNC
271 * @tc.function: RemoveListenerAndDeathRecipient
272 * @tc.subfunction: NA
273 * @tc.envConditions: NA
274 */
275 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_RemoveListenerAndDeathRecipient_0100, TestSize.Level0)
276 {
277 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_RemoveListenerAndDeathRecipient_0100 start.");
278 wptr<IRemoteObject> remote;
279 auto ret = appRunningStatusModule_->RemoveListenerAndDeathRecipient(remote);
280 EXPECT_EQ(ret, ERR_INVALID_VALUE);
281 }
282
283 /**
284 * @tc.number: AppRunningStatusModuleTest_RemoveListenerAndDeathRecipient_0200
285 * @tc.desc: Test RemoveListenerAndDeathRecipient with valid remote object that exists
286 * @tc.type: FUNC
287 * @tc.function: RemoveListenerAndDeathRecipient
288 * @tc.subfunction: NA
289 * @tc.envConditions: NA
290 */
291 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_RemoveListenerAndDeathRecipient_0200, TestSize.Level0)
292 {
293 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_RemoveListenerAndDeathRecipient_0200 start.");
294 sptr<MockAppRunningStatusListener> listener = new MockAppRunningStatusListener();
295
296 // Register listener first
297 auto ret = appRunningStatusModule_->RegisterListener(listener);
298 EXPECT_EQ(ret, ERR_OK);
299
300 // Remove listener using remote object
301 wptr<IRemoteObject> remote = listener->AsObject();
302 ret = appRunningStatusModule_->RemoveListenerAndDeathRecipient(remote);
303 EXPECT_EQ(ret, ERR_OK);
304 }
305
306 /**
307 * @tc.number: AppRunningStatusModuleTest_RemoveListenerAndDeathRecipient_0300
308 * @tc.desc: Test RemoveListenerAndDeathRecipient with remote object that doesn't exist in listeners
309 * @tc.type: FUNC
310 * @tc.function: RemoveListenerAndDeathRecipient
311 * @tc.subfunction: NA
312 * @tc.envConditions: NA
313 */
314 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_RemoveListenerAndDeathRecipient_0300, TestSize.Level0)
315 {
316 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_RemoveListenerAndDeathRecipient_0300 start.");
317 sptr<MockAppRunningStatusListener> listener = new MockAppRunningStatusListener();
318
319 // Don't register listener, directly try to remove
320 wptr<IRemoteObject> remote = listener->AsObject();
321 auto ret = appRunningStatusModule_->RemoveListenerAndDeathRecipient(remote);
322 EXPECT_EQ(ret, ERR_INVALID_OPERATION);
323 }
324
325 /**
326 * @tc.number: AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0400
327 * @tc.desc: Test NotifyAppRunningStatusEvent with null listener in listeners list
328 * @tc.type: FUNC
329 * @tc.function: NotifyAppRunningStatusEvent
330 * @tc.subfunction: NA
331 * @tc.envConditions: NA
332 */
333 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0400, TestSize.Level0)
334 {
335 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_NotifyAppRunningStatusEvent_0400 start.");
336 sptr<MockAppRunningStatusListener> listener = new MockAppRunningStatusListener();
337
338 // Register listener
339 auto ret = appRunningStatusModule_->RegisterListener(listener);
340 EXPECT_EQ(ret, ERR_OK);
341
342 {
343 std::lock_guard<std::mutex> lock(appRunningStatusModule_->listenerMutex_);
344 sptr<AppRunningStatusListenerInterface> nullListener = nullptr;
345 sptr<IRemoteObject::DeathRecipient> nullRecipient = nullptr;
346 appRunningStatusModule_->listeners_.emplace(nullListener, nullRecipient);
347 }
348
349 std::string bundleName = "com.test.bundle";
350 int32_t uid = 1000;
351 RunningStatus runningStatus = RunningStatus::APP_RUNNING_START;
352
353 appRunningStatusModule_->NotifyAppRunningStatusEvent(bundleName, uid, runningStatus);
354
355 EXPECT_EQ(listener->notifyCount_, 1);
356 EXPECT_EQ(listener->bundle_, bundleName);
357 EXPECT_EQ(listener->uid_, uid);
358 EXPECT_EQ(listener->runningStatus_, runningStatus);
359 }
360
361 /**
362 * @tc.number: AppRunningStatusModuleTest_ClientDeathRecipient_0200
363 * @tc.desc: Test ClientDeathRecipient OnRemoteDied with valid appRunningStatus
364 * @tc.type: FUNC
365 * @tc.function: ClientDeathRecipient::OnRemoteDied
366 * @tc.subfunction: NA
367 * @tc.envConditions: NA
368 */
369 HWTEST_F(AppRunningStatusModuleTest, AppRunningStatusModuleTest_ClientDeathRecipient_0100, TestSize.Level0)
370 {
371 TAG_LOGD(AAFwkTag::TEST, "AppRunningStatusModuleTest_ClientDeathRecipient_0100 start.");
372 sptr<MockAppRunningStatusListener> listener = new MockAppRunningStatusListener();
373
374 auto ret = appRunningStatusModule_->RegisterListener(listener);
375 EXPECT_EQ(ret, ERR_OK);
376
377 sptr<IRemoteObject::DeathRecipient> deathRecipient;
378 {
379 std::lock_guard<std::mutex> lock(appRunningStatusModule_->listenerMutex_);
380 auto it = appRunningStatusModule_->listeners_.find(listener);
381 EXPECT_NE(it, appRunningStatusModule_->listeners_.end());
382 deathRecipient = it->second;
383 }
384
385 wptr<IRemoteObject> remote = listener->AsObject();
386
387 deathRecipient->OnRemoteDied(remote);
388 {
389 std::lock_guard<std::mutex> lock(appRunningStatusModule_->listenerMutex_);
390 auto it2 = appRunningStatusModule_->listeners_.find(listener);
391 EXPECT_EQ(it2, appRunningStatusModule_->listeners_.end());
392 }
393 }
394
395 } // namespace AbilityRuntime
396 } // namespace OHOS
397