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 "async_shutdown_callback_test.h"
17 
18 #include <condition_variable>
19 #include <future>
20 #include <mutex>
21 #include "power_log.h"
22 #include "power_mgr_client.h"
23 #include "power_mgr_service.h"
24 #include "shutdown/shutdown_client.h"
25 
26 #include "mock_power_action.h"
27 #include "mock_state_action.h"
28 
29 namespace OHOS {
30 namespace PowerMgr {
31 namespace UnitTest {
32 namespace {
33 sptr<PowerMgrService> g_service = nullptr;
34 MockPowerAction* g_mockPowerAction = nullptr;
35 MockStateAction* g_mockStateAction = nullptr;
36 std::condition_variable g_cv;
37 std::mutex g_mtx;
38 bool g_isHighPriority = false;
39 bool g_isDefaultPriority = false;
40 bool g_isLowPriority = false;
41 const int32_t TIMEOUT_SEC = 5;
42 }
43 using namespace testing::ext;
44 using namespace std;
SetUpTestCase()45 void AsyncShutdownCallbackTest::SetUpTestCase()
46 {
47     // create singleton service object at the beginning
48     g_service = DelayedSpSingleton<PowerMgrService>::GetInstance();
49     g_service->OnStart();
50 }
51 
TearDownTestCase()52 void AsyncShutdownCallbackTest::TearDownTestCase()
53 {
54     g_service->OnStop();
55     DelayedSpSingleton<PowerMgrService>::DestroyInstance();
56 }
57 
SetUp()58 void AsyncShutdownCallbackTest::SetUp()
59 {
60     g_isHighPriority = false;
61     g_isDefaultPriority = false;
62     g_isLowPriority = false;
63     g_mockPowerAction = new MockPowerAction();
64     g_mockStateAction = new MockStateAction();
65     auto shutdownController = g_service->GetShutdownController();
66     if (shutdownController->IsShuttingDown()) {
67         // wait for detached threads to finish before next testcase
68         sleep(1);
69     }
70     shutdownController->EnableMock(g_mockPowerAction, g_mockStateAction);
71 }
72 
TearDown()73 void AsyncShutdownCallbackTest::TearDown()
74 {}
75 
OnAsyncShutdown()76 void AsyncShutdownCallbackTest::AsyncShutdownCallback::OnAsyncShutdown()
77 {
78     g_isDefaultPriority = true;
79     g_cv.notify_one();
80 }
81 
OnAsyncShutdown()82 void AsyncShutdownCallbackTest::HighPriorityAsyncShutdownCallback::OnAsyncShutdown()
83 {
84     g_isHighPriority = true;
85     g_cv.notify_one();
86 }
87 
OnAsyncShutdown()88 void AsyncShutdownCallbackTest::LowPriorityAsyncShutdownCallback::OnAsyncShutdown()
89 {
90     g_isLowPriority = true;
91     g_cv.notify_one();
92 }
93 
OnAsyncShutdown()94 void AsyncShutdownCallbackTest::NotAsyncShutdownCallback::OnAsyncShutdown()
95 {
96 }
97 
OnAsyncShutdownOrReboot(bool isReboot)98 void AsyncShutdownCallbackTest::AsyncShutdownOrRebootCallback::OnAsyncShutdownOrReboot(bool isReboot)
99 {
100     g_isDefaultPriority = true;
101     g_cv.notify_one();
102 }
103 
OnAsyncShutdownOrReboot(bool isReboot)104 void AsyncShutdownCallbackTest::HighPriorityAsyncShutdownOrRebootCallback::OnAsyncShutdownOrReboot(bool isReboot)
105 {
106     g_isHighPriority = true;
107     g_cv.notify_one();
108 }
109 
OnAsyncShutdownOrReboot(bool isReboot)110 void AsyncShutdownCallbackTest::LowPriorityAsyncShutdownOrRebootCallback::OnAsyncShutdownOrReboot(bool isReboot)
111 {
112     g_isLowPriority = true;
113     g_cv.notify_one();
114 }
115 
OnAsyncShutdownOrReboot(bool isReboot)116 void AsyncShutdownCallbackTest::NotAsyncShutdownOrRebootCallback::OnAsyncShutdownOrReboot(bool isReboot)
117 {
118 }
119 
WaitingCallback(bool & isPriority)120 static bool WaitingCallback(bool &isPriority)
121 {
122     std::unique_lock<std::mutex> lck(g_mtx);
123     auto callbackStart = [&]() {
124         while (!isPriority) {
125             g_cv.wait(lck);
126         }
127     };
128 
129     packaged_task<void()> callbackTask(callbackStart);
130     future<void> fut = callbackTask.get_future();
131     make_unique<thread>(std::move(callbackTask))->detach();
132     future_status status = fut.wait_for(std::chrono::seconds(TIMEOUT_SEC));
133     if (status == future_status::timeout) {
134         return false;
135     }
136     return true;
137 }
138 
139 /**
140  * @tc.name: AsyncShutdownCallbackk001
141  * @tc.desc: Test asynchronous shutdown callback for shutdown and reboot
142  * @tc.type: FUNC
143  */
144 HWTEST_F(AsyncShutdownCallbackTest, AsyncShutdownCallbackk001, TestSize.Level0)
145 {
146     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallbackk001 start");
147     auto callback = new AsyncShutdownCallback();
148     g_service->RegisterShutdownCallback(callback, ShutdownPriority::DEFAULT);
149     auto callback2 = new AsyncShutdownOrRebootCallback();
150     g_service->RegisterShutdownCallback(callback2, ShutdownPriority::DEFAULT);
151 
152     g_service->RebootDevice("test_reboot");
153     EXPECT_TRUE(WaitingCallback(g_isDefaultPriority));
154 
155     g_service->ShutDownDevice("test_shutdown");
156     EXPECT_TRUE(WaitingCallback(g_isDefaultPriority));
157     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallback001 end");
158 }
159 
160 /**
161  * @tc.name: AsyncShutdownCallbackk002
162  * @tc.desc: Test the low and default priority of asynchronous shutdown callback
163  * @tc.type: FUNC
164  */
165 HWTEST_F(AsyncShutdownCallbackTest, AsyncShutdownCallbackk002, TestSize.Level0)
166 {
167     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallbackk002 start");
168     auto lowPriorityCallback = new LowPriorityAsyncShutdownCallback();
169     g_service->RegisterShutdownCallback(lowPriorityCallback, ShutdownPriority::LOW);
170     auto defaultPriorityCallback = new AsyncShutdownCallback();
171     g_service->RegisterShutdownCallback(defaultPriorityCallback, ShutdownPriority::DEFAULT);
172 
173     g_service->ShutDownDevice("test_shutdown");
174     EXPECT_TRUE(WaitingCallback(g_isDefaultPriority));
175     EXPECT_TRUE(WaitingCallback(g_isLowPriority));
176     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallbackk002 end");
177 }
178 
179 /**
180  * @tc.name: AsyncShutdownCallbackk003
181  * @tc.desc: Test the low and high priority of asynchronous shutdown callback
182  * @tc.type: FUNC
183  */
184 HWTEST_F(AsyncShutdownCallbackTest, AsyncShutdownCallbackk003, TestSize.Level0)
185 {
186     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallbackk003 start");
187     auto lowPriorityCallback = new LowPriorityAsyncShutdownCallback();
188     g_service->RegisterShutdownCallback(lowPriorityCallback, ShutdownPriority::LOW);
189     auto highPriorityCallback = new HighPriorityAsyncShutdownCallback();
190     g_service->RegisterShutdownCallback(highPriorityCallback, ShutdownPriority::HIGH);
191 
192     g_service->ShutDownDevice("test_shutdown");
193     EXPECT_TRUE(WaitingCallback(g_isHighPriority));
194     EXPECT_TRUE(WaitingCallback(g_isLowPriority));
195     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallbackk003 end");
196 }
197 
198 /**
199  * @tc.name: AsyncShutdownCallback004
200  * @tc.desc: Test the default and high priority of asynchronous shutdown callback
201  * @tc.type: FUNC
202  */
203 HWTEST_F(AsyncShutdownCallbackTest, AsyncShutdownCallback004, TestSize.Level0)
204 {
205     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallback004 start");
206     auto defaultPriorityCallback = new AsyncShutdownCallback();
207     g_service->RegisterShutdownCallback(defaultPriorityCallback, ShutdownPriority::DEFAULT);
208     auto highPriorityCallback = new HighPriorityAsyncShutdownCallback();
209     g_service->RegisterShutdownCallback(highPriorityCallback, ShutdownPriority::HIGH);
210 
211     g_service->ShutDownDevice("test_shutdown");
212     EXPECT_TRUE(WaitingCallback(g_isHighPriority));
213     EXPECT_TRUE(WaitingCallback(g_isDefaultPriority));
214     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallback004 end");
215 }
216 
217 /**
218  * @tc.name: AsyncShutdownCallback005
219  * @tc.desc: Test do not asynchronous shutdown
220  * @tc.type: FUNC
221  */
222 HWTEST_F(AsyncShutdownCallbackTest, AsyncShutdownCallback005, TestSize.Level0)
223 {
224     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallback005 start");
225     auto notAsyncCallback = new NotAsyncShutdownCallback();
226     g_service->RegisterShutdownCallback(notAsyncCallback, ShutdownPriority::DEFAULT);
227 
228     EXPECT_CALL(*g_mockPowerAction, Reboot(std::string("test_reboot"))).Times(1);
229     g_service->RebootDevice("test_reboot");
230 
231     EXPECT_CALL(*g_mockPowerAction, Shutdown(std::string("test_shutdown"))).Times(1);
232     g_service->ShutDownDevice("test_shutdown");
233 
234     // wait for detached threads to finish
235     sleep(1);
236     POWER_HILOGI(LABEL_TEST, "AsyncShutdownCallback005 end");
237 }
238 } // namespace UnitTest
239 } // namespace PowerMgr
240 } // namespace OHOS
241