Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1144)

Side by Side Diff: ash/system/chromeos/power/tray_power_unittest.cc

Issue 2072013002: mash: Move tray settings and deps to common. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Undo 'git cl format' and nullptr changes. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
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 "ash/system/chromeos/power/tray_power.h"
6
7 #include <map>
8 #include <memory>
9 #include <string>
10
11 #include "ash/ash_switches.h"
12 #include "ash/test/ash_test_base.h"
13 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
14 #include "ui/message_center/fake_message_center.h"
15
16 using message_center::Notification;
17 using power_manager::PowerSupplyProperties;
18
19 namespace {
20
21 class MockMessageCenter : public message_center::FakeMessageCenter {
22 public:
23 MockMessageCenter() : add_count_(0), remove_count_(0), update_count_(0) {}
24 ~MockMessageCenter() override {}
25
26 int add_count() const { return add_count_; }
27 int remove_count() const { return remove_count_; }
28 int update_count() const { return update_count_; }
29
30 // message_center::FakeMessageCenter overrides:
31 void AddNotification(std::unique_ptr<Notification> notification) override {
32 add_count_++;
33 notifications_.insert(
34 std::make_pair(notification->id(), std::move(notification)));
35 }
36 void RemoveNotification(const std::string& id, bool by_user) override {
37 Notification* notification = FindVisibleNotificationById(id);
38 if (notification && notification->delegate())
39 notification->delegate()->Close(by_user);
40 remove_count_++;
41 notifications_.erase(id);
42 }
43 void UpdateNotification(
44 const std::string& id,
45 std::unique_ptr<Notification> new_notification) override {
46 update_count_++;
47 Notification* notification = FindVisibleNotificationById(id);
48 if (notification)
49 notifications_.erase(id);
50 notifications_.insert(
51 std::make_pair(new_notification->id(), std::move(new_notification)));
52 }
53
54 Notification* FindVisibleNotificationById(const std::string& id) override {
55 auto it = notifications_.find(id);
56 return it == notifications_.end() ? NULL : it->second.get();
57 }
58
59 private:
60 int add_count_;
61 int remove_count_;
62 int update_count_;
63 std::map<std::string, std::unique_ptr<Notification>> notifications_;
64
65 DISALLOW_COPY_AND_ASSIGN(MockMessageCenter);
66 };
67
68 } // namespace
69
70 namespace ash {
71
72 class TrayPowerTest : public test::AshTestBase {
73 public:
74 TrayPowerTest() {}
75 ~TrayPowerTest() override {}
76
77 MockMessageCenter* message_center() { return message_center_.get(); }
78 TrayPower* tray_power() { return tray_power_.get(); }
79
80 // test::AshTestBase::SetUp() overrides:
81 void SetUp() override {
82 test::AshTestBase::SetUp();
83 message_center_.reset(new MockMessageCenter());
84 tray_power_.reset(new TrayPower(NULL, message_center_.get()));
85 }
86
87 void TearDown() override {
88 tray_power_.reset();
89 message_center_.reset();
90 test::AshTestBase::TearDown();
91 }
92
93 TrayPower::NotificationState notification_state() const {
94 return tray_power_->notification_state_;
95 }
96
97 bool MaybeShowUsbChargerNotification(const PowerSupplyProperties& proto) {
98 PowerStatus::Get()->SetProtoForTesting(proto);
99 return tray_power_->MaybeShowUsbChargerNotification();
100 }
101
102 void MaybeShowDualRoleNotification(const PowerSupplyProperties& proto) {
103 PowerStatus::Get()->SetProtoForTesting(proto);
104 tray_power_->MaybeShowDualRoleNotification();
105 }
106
107 void UpdateNotificationState(const PowerSupplyProperties& proto,
108 TrayPower::NotificationState expected_state,
109 bool expected_add,
110 bool expected_remove) {
111 int prev_add = message_center_->add_count();
112 int prev_remove = message_center_->remove_count();
113 PowerStatus::Get()->SetProtoForTesting(proto);
114 tray_power_->OnPowerStatusChanged();
115 EXPECT_EQ(expected_state, notification_state());
116 EXPECT_EQ(expected_add, message_center_->add_count() == prev_add + 1);
117 EXPECT_EQ(expected_remove,
118 message_center_->remove_count() == prev_remove + 1);
119 }
120
121 void SetUsbChargerConnected(bool connected) {
122 tray_power_->usb_charger_was_connected_ = connected;
123 }
124
125 // Returns a discharging PowerSupplyProperties more appropriate for testing.
126 static PowerSupplyProperties DefaultPowerSupplyProperties() {
127 PowerSupplyProperties proto;
128 proto.set_external_power(
129 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
130 proto.set_battery_state(
131 power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
132 proto.set_battery_percent(50.0);
133 proto.set_battery_time_to_empty_sec(3 * 60 * 60);
134 proto.set_battery_time_to_full_sec(2 * 60 * 60);
135 proto.set_is_calculating_battery_time(false);
136 return proto;
137 }
138
139 private:
140 std::unique_ptr<MockMessageCenter> message_center_;
141 std::unique_ptr<TrayPower> tray_power_;
142
143 DISALLOW_COPY_AND_ASSIGN(TrayPowerTest);
144 };
145
146 TEST_F(TrayPowerTest, MaybeShowUsbChargerNotification) {
147 PowerSupplyProperties discharging = DefaultPowerSupplyProperties();
148 EXPECT_FALSE(MaybeShowUsbChargerNotification(discharging));
149 EXPECT_EQ(0, message_center()->add_count());
150 EXPECT_EQ(0, message_center()->remove_count());
151
152 // Notification shows when connecting a USB charger.
153 PowerSupplyProperties usb_connected = DefaultPowerSupplyProperties();
154 usb_connected.set_external_power(
155 power_manager::PowerSupplyProperties_ExternalPower_USB);
156 EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
157 EXPECT_EQ(1, message_center()->add_count());
158 EXPECT_EQ(0, message_center()->remove_count());
159 SetUsbChargerConnected(true);
160
161 // Change in charge does not trigger the notification again.
162 PowerSupplyProperties more_charge = DefaultPowerSupplyProperties();
163 more_charge.set_external_power(
164 power_manager::PowerSupplyProperties_ExternalPower_USB);
165 more_charge.set_battery_time_to_full_sec(60 * 60);
166 more_charge.set_battery_percent(75.0);
167 EXPECT_FALSE(MaybeShowUsbChargerNotification(more_charge));
168 EXPECT_EQ(1, message_center()->add_count());
169 EXPECT_EQ(0, message_center()->remove_count());
170
171 // Disconnecting a USB charger with the notification showing should close
172 // the notification.
173 EXPECT_TRUE(MaybeShowUsbChargerNotification(discharging));
174 EXPECT_EQ(1, message_center()->add_count());
175 EXPECT_EQ(1, message_center()->remove_count());
176 SetUsbChargerConnected(false);
177
178 // Notification shows when connecting a USB charger again.
179 EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
180 EXPECT_EQ(2, message_center()->add_count());
181 EXPECT_EQ(1, message_center()->remove_count());
182 SetUsbChargerConnected(true);
183
184 // Notification hides when external power switches to AC.
185 PowerSupplyProperties ac_charger = DefaultPowerSupplyProperties();
186 ac_charger.set_external_power(
187 power_manager::PowerSupplyProperties_ExternalPower_AC);
188 EXPECT_TRUE(MaybeShowUsbChargerNotification(ac_charger));
189 EXPECT_EQ(2, message_center()->add_count());
190 EXPECT_EQ(2, message_center()->remove_count());
191 SetUsbChargerConnected(false);
192
193 // Notification shows when external power switches back to USB.
194 EXPECT_TRUE(MaybeShowUsbChargerNotification(usb_connected));
195 EXPECT_EQ(3, message_center()->add_count());
196 EXPECT_EQ(2, message_center()->remove_count());
197 SetUsbChargerConnected(true);
198
199 // Notification does not re-appear after being manually dismissed if
200 // power supply flickers between AC and USB charger.
201 message_center()->RemoveNotification(TrayPower::kUsbNotificationId, true);
202 EXPECT_EQ(3, message_center()->remove_count());
203 EXPECT_TRUE(MaybeShowUsbChargerNotification(ac_charger));
204 SetUsbChargerConnected(false);
205 EXPECT_FALSE(MaybeShowUsbChargerNotification(usb_connected));
206 EXPECT_EQ(3, message_center()->add_count());
207 SetUsbChargerConnected(true);
208
209 // Notification appears again after being manually dismissed if the charger
210 // is removed, and then a USB charger is attached.
211 MaybeShowUsbChargerNotification(discharging);
212 EXPECT_EQ(3, message_center()->add_count());
213 SetUsbChargerConnected(false);
214 MaybeShowUsbChargerNotification(usb_connected);
215 EXPECT_EQ(4, message_center()->add_count());
216 SetUsbChargerConnected(true);
217 }
218
219 TEST_F(TrayPowerTest, MaybeShowDualRoleNotification) {
220 PowerSupplyProperties discharging = DefaultPowerSupplyProperties();
221 discharging.set_supports_dual_role_devices(true);
222 MaybeShowDualRoleNotification(discharging);
223 EXPECT_EQ(0, message_center()->add_count());
224 EXPECT_EQ(0, message_center()->update_count());
225 EXPECT_EQ(0, message_center()->remove_count());
226
227 // Notification shows when connecting a dual-role device.
228 PowerSupplyProperties dual_role = DefaultPowerSupplyProperties();
229 dual_role.set_supports_dual_role_devices(true);
230 power_manager::PowerSupplyProperties_PowerSource* source =
231 dual_role.add_available_external_power_source();
232 source->set_id("dual-role1");
233 source->set_active_by_default(false);
234 MaybeShowDualRoleNotification(dual_role);
235 EXPECT_EQ(1, message_center()->add_count());
236 EXPECT_EQ(0, message_center()->update_count());
237 EXPECT_EQ(0, message_center()->remove_count());
238
239 // Connecting another dual-role device updates the notification to be plural.
240 source = dual_role.add_available_external_power_source();
241 source->set_id("dual-role2");
242 source->set_active_by_default(false);
243 MaybeShowDualRoleNotification(dual_role);
244 EXPECT_EQ(1, message_center()->add_count());
245 EXPECT_EQ(1, message_center()->update_count());
246 EXPECT_EQ(0, message_center()->remove_count());
247
248 // Connecting a 3rd dual-role device doesn't affect the notification.
249 source = dual_role.add_available_external_power_source();
250 source->set_id("dual-role3");
251 source->set_active_by_default(false);
252 MaybeShowDualRoleNotification(dual_role);
253 EXPECT_EQ(1, message_center()->add_count());
254 EXPECT_EQ(1, message_center()->update_count());
255 EXPECT_EQ(0, message_center()->remove_count());
256
257 // Connecting a legacy USB device removes the notification.
258 PowerSupplyProperties legacy(dual_role);
259 power_manager::PowerSupplyProperties_PowerSource* legacy_source =
260 legacy.add_available_external_power_source();
261 legacy_source->set_id("legacy");
262 legacy_source->set_active_by_default(true);
263 legacy.set_external_power_source_id("legacy");
264 legacy.set_external_power(
265 power_manager::PowerSupplyProperties_ExternalPower_USB);
266 MaybeShowDualRoleNotification(legacy);
267 EXPECT_EQ(1, message_center()->add_count());
268 EXPECT_EQ(1, message_center()->update_count());
269 EXPECT_EQ(1, message_center()->remove_count());
270
271 // Removing the legacy USB device adds the notification again.
272 MaybeShowDualRoleNotification(dual_role);
273 EXPECT_EQ(2, message_center()->add_count());
274 EXPECT_EQ(1, message_center()->update_count());
275 EXPECT_EQ(1, message_center()->remove_count());
276
277 // Charging from the device updates the notification.
278 dual_role.set_external_power_source_id("dual-role1");
279 dual_role.set_external_power(
280 power_manager::PowerSupplyProperties_ExternalPower_USB);
281 MaybeShowDualRoleNotification(dual_role);
282 EXPECT_EQ(2, message_center()->add_count());
283 EXPECT_EQ(2, message_center()->update_count());
284 EXPECT_EQ(1, message_center()->remove_count());
285
286 // Adding a device as a sink doesn't change the notification, because the
287 // notification exposes the source.
288 source = dual_role.add_available_external_power_source();
289 source->set_active_by_default(false);
290 MaybeShowDualRoleNotification(dual_role);
291 EXPECT_EQ(2, message_center()->add_count());
292 EXPECT_EQ(2, message_center()->update_count());
293 EXPECT_EQ(1, message_center()->remove_count());
294
295 // Changing the source to a sink changes the notification.
296 dual_role.set_external_power_source_id("");
297 dual_role.set_external_power(
298 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
299 MaybeShowDualRoleNotification(dual_role);
300 EXPECT_EQ(2, message_center()->add_count());
301 EXPECT_EQ(3, message_center()->update_count());
302 EXPECT_EQ(1, message_center()->remove_count());
303
304 // An unrelated change has no effect.
305 dual_role.set_battery_time_to_empty_sec(2 * 60 * 60);
306 MaybeShowDualRoleNotification(dual_role);
307 EXPECT_EQ(2, message_center()->add_count());
308 EXPECT_EQ(3, message_center()->update_count());
309 EXPECT_EQ(1, message_center()->remove_count());
310
311 // Removing devices hides the notification.
312 MaybeShowDualRoleNotification(discharging);
313 EXPECT_EQ(2, message_center()->add_count());
314 EXPECT_EQ(3, message_center()->update_count());
315 EXPECT_EQ(2, message_center()->remove_count());
316 }
317
318 TEST_F(TrayPowerTest, UpdateNotificationState) {
319 // No notifications when no battery present.
320 PowerSupplyProperties no_battery = DefaultPowerSupplyProperties();
321 no_battery.set_external_power(
322 power_manager::PowerSupplyProperties_ExternalPower_AC);
323 no_battery.set_battery_state(
324 power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT);
325 {
326 SCOPED_TRACE("No notifications when no battery present");
327 UpdateNotificationState(no_battery, TrayPower::NOTIFICATION_NONE, false,
328 false);
329 }
330
331 // No notification when calculating remaining battery time.
332 PowerSupplyProperties calculating = DefaultPowerSupplyProperties();
333 calculating.set_is_calculating_battery_time(true);
334 {
335 SCOPED_TRACE("No notification when calculating remaining battery time");
336 UpdateNotificationState(calculating, TrayPower::NOTIFICATION_NONE, false,
337 false);
338 }
339
340 // No notification when charging.
341 PowerSupplyProperties charging = DefaultPowerSupplyProperties();
342 charging.set_external_power(
343 power_manager::PowerSupplyProperties_ExternalPower_AC);
344 charging.set_battery_state(
345 power_manager::PowerSupplyProperties_BatteryState_CHARGING);
346 {
347 SCOPED_TRACE("No notification when charging");
348 UpdateNotificationState(charging, TrayPower::NOTIFICATION_NONE, false,
349 false);
350 }
351
352 // When the rounded minutes-to-empty are above the threshold, no notification
353 // should be shown.
354 PowerSupplyProperties low = DefaultPowerSupplyProperties();
355 low.set_battery_time_to_empty_sec(TrayPower::kLowPowerMinutes * 60 + 30);
356 {
357 SCOPED_TRACE("No notification when time to empty above threshold");
358 UpdateNotificationState(low, TrayPower::NOTIFICATION_NONE, false, false);
359 }
360
361 // When the rounded value matches the threshold, the notification should
362 // appear.
363 low.set_battery_time_to_empty_sec(TrayPower::kLowPowerMinutes * 60 + 29);
364 {
365 SCOPED_TRACE("Notification when time to empty matches threshold");
366 UpdateNotificationState(low, TrayPower::NOTIFICATION_LOW_POWER, true,
367 false);
368 }
369
370 // It should persist at lower values.
371 low.set_battery_time_to_empty_sec(TrayPower::kLowPowerMinutes * 60 - 20);
372 {
373 SCOPED_TRACE("Notification persists at lower values");
374 UpdateNotificationState(low, TrayPower::NOTIFICATION_LOW_POWER, false,
375 false);
376 }
377
378 // The critical low battery notification should be shown when the rounded
379 // value is at the lower threshold.
380 PowerSupplyProperties critical = DefaultPowerSupplyProperties();
381 critical.set_battery_time_to_empty_sec(TrayPower::kCriticalMinutes * 60 + 29);
382 {
383 SCOPED_TRACE("Critical notification when time to empty is critical");
384 UpdateNotificationState(critical, TrayPower::NOTIFICATION_CRITICAL, true,
385 true);
386 }
387
388 // The notification should be dismissed when the no-warning threshold is
389 // reached.
390 PowerSupplyProperties safe = DefaultPowerSupplyProperties();
391 safe.set_battery_time_to_empty_sec(TrayPower::kNoWarningMinutes * 60 - 29);
392 {
393 SCOPED_TRACE("Notification removed when battery not low");
394 UpdateNotificationState(safe, TrayPower::NOTIFICATION_NONE, false, true);
395 }
396
397 // Test that rounded percentages are used when a USB charger is connected.
398 PowerSupplyProperties low_usb = DefaultPowerSupplyProperties();
399 low_usb.set_external_power(
400 power_manager::PowerSupplyProperties_ExternalPower_USB);
401 low_usb.set_battery_percent(TrayPower::kLowPowerPercentage + 0.5);
402 {
403 SCOPED_TRACE("No notification for rounded battery percent");
404 UpdateNotificationState(low_usb, TrayPower::NOTIFICATION_NONE, true, false);
405 }
406
407 low_usb.set_battery_percent(TrayPower::kLowPowerPercentage + 0.49);
408 {
409 SCOPED_TRACE("Notification for rounded low power percent");
410 UpdateNotificationState(low_usb, TrayPower::NOTIFICATION_LOW_POWER, true,
411 false);
412 }
413
414 PowerSupplyProperties critical_usb = DefaultPowerSupplyProperties();
415 critical_usb.set_external_power(
416 power_manager::PowerSupplyProperties_ExternalPower_USB);
417 critical_usb.set_battery_percent(TrayPower::kCriticalPercentage + 0.2);
418 {
419 SCOPED_TRACE("Notification for rounded critical power percent");
420 UpdateNotificationState(critical_usb, TrayPower::NOTIFICATION_CRITICAL,
421 true, true);
422 }
423
424 PowerSupplyProperties safe_usb = DefaultPowerSupplyProperties();
425 safe_usb.set_external_power(
426 power_manager::PowerSupplyProperties_ExternalPower_USB);
427 safe_usb.set_battery_percent(TrayPower::kNoWarningPercentage - 0.1);
428 {
429 SCOPED_TRACE("Notification removed for rounded percent above threshold");
430 UpdateNotificationState(safe_usb, TrayPower::NOTIFICATION_NONE, false,
431 true);
432 }
433 }
434
435 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698