1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/power_monitor/power_monitor.h"
6
7 #include <optional>
8
9 #include "base/test/power_monitor_test.h"
10 #include "base/test/task_environment.h"
11 #include "power_observer.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace base {
15 namespace test {
16
17 class PowerMonitorTest : public testing::Test {
18 public:
19 PowerMonitorTest(const PowerMonitorTest&) = delete;
20 PowerMonitorTest& operator=(const PowerMonitorTest&) = delete;
21
22 protected:
23 PowerMonitorTest() = default;
24
PowerMonitorInitialize()25 void PowerMonitorInitialize() { power_monitor_source_.emplace(); }
26
source()27 ScopedPowerMonitorTestSource& source() {
28 return power_monitor_source_.value();
29 }
30
31 private:
32 TaskEnvironment task_environment_;
33 std::optional<ScopedPowerMonitorTestSource> power_monitor_source_;
34 };
35
36 // PowerMonitorSource is tightly coupled with the PowerMonitor, so this test
37 // covers both classes.
TEST_F(PowerMonitorTest,PowerNotifications)38 TEST_F(PowerMonitorTest, PowerNotifications) {
39 const int kObservers = 5;
40
41 PowerMonitorInitialize();
42
43 PowerMonitorTestObserver observers[kObservers];
44 auto* power_monitor = PowerMonitor::GetInstance();
45 for (auto& index : observers) {
46 power_monitor->AddPowerSuspendObserver(&index);
47 power_monitor->AddPowerStateObserver(&index);
48 power_monitor->AddPowerThermalObserver(&index);
49 }
50
51 // Sending resume when not suspended should have no effect.
52 source().GenerateResumeEvent();
53 EXPECT_EQ(observers[0].resumes(), 0);
54
55 // Pretend we suspended.
56 source().GenerateSuspendEvent();
57 // Ensure all observers were notified of the event
58 for (const auto& index : observers)
59 EXPECT_EQ(index.suspends(), 1);
60
61 // Send a second suspend notification. This should be suppressed.
62 source().GenerateSuspendEvent();
63 EXPECT_EQ(observers[0].suspends(), 1);
64
65 // Pretend we were awakened.
66 source().GenerateResumeEvent();
67 EXPECT_EQ(observers[0].resumes(), 1);
68
69 // Send a duplicate resume notification. This should be suppressed.
70 source().GenerateResumeEvent();
71 EXPECT_EQ(observers[0].resumes(), 1);
72
73 // Pretend the device has gone on battery power
74 source().GeneratePowerStateEvent(
75 PowerStateObserver::BatteryPowerStatus::kBatteryPower);
76 EXPECT_EQ(observers[0].power_state_changes(), 1);
77 EXPECT_EQ(observers[0].last_power_status(),
78 PowerStateObserver::BatteryPowerStatus::kBatteryPower);
79
80 // Repeated indications the device is on battery power should be suppressed.
81 source().GeneratePowerStateEvent(
82 PowerStateObserver::BatteryPowerStatus::kBatteryPower);
83 EXPECT_EQ(observers[0].power_state_changes(), 1);
84
85 // Pretend the device has gone off battery power
86 source().GeneratePowerStateEvent(
87 PowerStateObserver::BatteryPowerStatus::kExternalPower);
88 EXPECT_EQ(observers[0].power_state_changes(), 2);
89 EXPECT_EQ(observers[0].last_power_status(),
90 PowerStateObserver::BatteryPowerStatus::kExternalPower);
91
92 // Repeated indications the device is off battery power should be suppressed.
93 source().GeneratePowerStateEvent(
94 PowerStateObserver::BatteryPowerStatus::kExternalPower);
95 EXPECT_EQ(observers[0].power_state_changes(), 2);
96
97 // Send speed limit change notifications.
98 source().GenerateSpeedLimitEvent(666);
99 EXPECT_EQ(observers[0].speed_limit_changes(), 1);
100 EXPECT_EQ(observers[0].last_speed_limit(), 666);
101 source().GenerateSpeedLimitEvent(777);
102 EXPECT_EQ(observers[0].speed_limit_changes(), 2);
103 EXPECT_EQ(observers[0].last_speed_limit(), 777);
104
105 EXPECT_EQ(observers[0].thermal_state_changes(), 0);
106
107 // Send a power thermal change notification.
108 source().GenerateThermalThrottlingEvent(
109 PowerThermalObserver::DeviceThermalState::kNominal);
110 EXPECT_EQ(observers[0].thermal_state_changes(), 1);
111 EXPECT_EQ(observers[0].last_thermal_state(),
112 PowerThermalObserver::DeviceThermalState::kNominal);
113
114 // Send a duplicate power thermal notification. This should be suppressed.
115 source().GenerateThermalThrottlingEvent(
116 PowerThermalObserver::DeviceThermalState::kNominal);
117 EXPECT_EQ(observers[0].thermal_state_changes(), 1);
118
119 // Send a different power thermal change notification.
120 source().GenerateThermalThrottlingEvent(
121 PowerThermalObserver::DeviceThermalState::kFair);
122 EXPECT_EQ(observers[0].thermal_state_changes(), 2);
123 EXPECT_EQ(observers[0].last_thermal_state(),
124 PowerThermalObserver::DeviceThermalState::kFair);
125
126 for (auto& index : observers) {
127 power_monitor->RemovePowerSuspendObserver(&index);
128 power_monitor->RemovePowerStateObserver(&index);
129 power_monitor->RemovePowerThermalObserver(&index);
130 }
131 }
132
TEST_F(PowerMonitorTest,ThermalThrottling)133 TEST_F(PowerMonitorTest, ThermalThrottling) {
134 PowerMonitorTestObserver observer;
135 auto* power_monitor = PowerMonitor::GetInstance();
136 power_monitor->AddPowerThermalObserver(&observer);
137
138 PowerMonitorInitialize();
139
140 constexpr PowerThermalObserver::DeviceThermalState kThermalStates[] = {
141 PowerThermalObserver::DeviceThermalState::kUnknown,
142 PowerThermalObserver::DeviceThermalState::kNominal,
143 PowerThermalObserver::DeviceThermalState::kFair,
144 PowerThermalObserver::DeviceThermalState::kSerious,
145 PowerThermalObserver::DeviceThermalState::kCritical};
146
147 for (const auto state : kThermalStates) {
148 source().GenerateThermalThrottlingEvent(state);
149 EXPECT_EQ(state, source().GetCurrentThermalState());
150 EXPECT_EQ(observer.last_thermal_state(), state);
151 }
152
153 power_monitor->RemovePowerThermalObserver(&observer);
154 }
155
TEST_F(PowerMonitorTest,AddPowerSuspendObserverBeforeAndAfterInitialization)156 TEST_F(PowerMonitorTest, AddPowerSuspendObserverBeforeAndAfterInitialization) {
157 PowerMonitorTestObserver observer1;
158 PowerMonitorTestObserver observer2;
159 auto* power_monitor = PowerMonitor::GetInstance();
160
161 // An observer is added before the PowerMonitor initialization.
162 power_monitor->AddPowerSuspendObserver(&observer1);
163
164 PowerMonitorInitialize();
165
166 // An observer is added after the PowerMonitor initialization.
167 power_monitor->AddPowerSuspendObserver(&observer2);
168
169 // Simulate suspend/resume notifications.
170 source().GenerateSuspendEvent();
171 EXPECT_EQ(observer1.suspends(), 1);
172 EXPECT_EQ(observer2.suspends(), 1);
173 EXPECT_EQ(observer1.resumes(), 0);
174 EXPECT_EQ(observer2.resumes(), 0);
175
176 source().GenerateResumeEvent();
177 EXPECT_EQ(observer1.resumes(), 1);
178 EXPECT_EQ(observer2.resumes(), 1);
179
180 power_monitor->RemovePowerSuspendObserver(&observer1);
181 power_monitor->RemovePowerSuspendObserver(&observer2);
182 }
183
TEST_F(PowerMonitorTest,AddPowerStateObserverBeforeAndAfterInitialization)184 TEST_F(PowerMonitorTest, AddPowerStateObserverBeforeAndAfterInitialization) {
185 PowerMonitorTestObserver observer1;
186 PowerMonitorTestObserver observer2;
187 auto* power_monitor = PowerMonitor::GetInstance();
188
189 // An observer is added before the PowerMonitor initialization.
190 power_monitor->AddPowerStateObserver(&observer1);
191
192 PowerMonitorInitialize();
193
194 // An observer is added after the PowerMonitor initialization.
195 power_monitor->AddPowerStateObserver(&observer2);
196
197 // Simulate power state transitions (e.g. battery on/off).
198 EXPECT_EQ(observer1.power_state_changes(), 0);
199 EXPECT_EQ(observer2.power_state_changes(), 0);
200 source().GeneratePowerStateEvent(
201 PowerStateObserver::BatteryPowerStatus::kBatteryPower);
202 EXPECT_EQ(observer1.power_state_changes(), 1);
203 EXPECT_EQ(observer2.power_state_changes(), 1);
204 source().GeneratePowerStateEvent(
205 PowerStateObserver::BatteryPowerStatus::kExternalPower);
206 EXPECT_EQ(observer1.power_state_changes(), 2);
207 EXPECT_EQ(observer2.power_state_changes(), 2);
208
209 power_monitor->RemovePowerStateObserver(&observer1);
210 power_monitor->RemovePowerStateObserver(&observer2);
211 }
212
TEST_F(PowerMonitorTest,SuspendStateReturnedFromAddObserver)213 TEST_F(PowerMonitorTest, SuspendStateReturnedFromAddObserver) {
214 PowerMonitorTestObserver observer1;
215 PowerMonitorTestObserver observer2;
216 auto* power_monitor = PowerMonitor::GetInstance();
217
218 PowerMonitorInitialize();
219
220 EXPECT_FALSE(power_monitor->AddPowerSuspendObserverAndReturnSuspendedState(
221 &observer1));
222
223 source().GenerateSuspendEvent();
224
225 EXPECT_TRUE(power_monitor->AddPowerSuspendObserverAndReturnSuspendedState(
226 &observer2));
227
228 EXPECT_EQ(observer1.suspends(), 1);
229 EXPECT_EQ(observer2.suspends(), 0);
230 EXPECT_EQ(observer1.resumes(), 0);
231 EXPECT_EQ(observer2.resumes(), 0);
232
233 power_monitor->RemovePowerSuspendObserver(&observer1);
234 power_monitor->RemovePowerSuspendObserver(&observer2);
235 }
236
TEST_F(PowerMonitorTest,PowerStateReturnedFromAddObserver)237 TEST_F(PowerMonitorTest, PowerStateReturnedFromAddObserver) {
238 PowerMonitorTestObserver observer1;
239 PowerMonitorTestObserver observer2;
240 auto* power_monitor = PowerMonitor::GetInstance();
241
242 PowerMonitorInitialize();
243
244 // An observer is added before the on-battery notification.
245 EXPECT_NE(power_monitor->AddPowerStateObserverAndReturnBatteryPowerStatus(
246 &observer1),
247 PowerStateObserver::BatteryPowerStatus::kBatteryPower);
248
249 source().GeneratePowerStateEvent(
250 PowerStateObserver::BatteryPowerStatus::kBatteryPower);
251
252 // An observer is added after the on-battery notification.
253 EXPECT_EQ(power_monitor->AddPowerStateObserverAndReturnBatteryPowerStatus(
254 &observer2),
255 PowerStateObserver::BatteryPowerStatus::kBatteryPower);
256
257 EXPECT_EQ(observer1.power_state_changes(), 1);
258 EXPECT_EQ(observer2.power_state_changes(), 0);
259
260 power_monitor->RemovePowerStateObserver(&observer1);
261 power_monitor->RemovePowerStateObserver(&observer2);
262 }
263
264 } // namespace test
265 } // namespace base
266