| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 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/common/system/chromeos/power/power_status.h" | |
| 6 | |
| 7 #include <memory> | |
| 8 | |
| 9 #include "base/message_loop/message_loop.h" | |
| 10 #include "base/run_loop.h" | |
| 11 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 14 | |
| 15 using power_manager::PowerSupplyProperties; | |
| 16 | |
| 17 namespace ash { | |
| 18 namespace { | |
| 19 | |
| 20 class TestObserver : public PowerStatus::Observer { | |
| 21 public: | |
| 22 TestObserver() : power_changed_count_(0) {} | |
| 23 ~TestObserver() override {} | |
| 24 | |
| 25 int power_changed_count() const { return power_changed_count_; } | |
| 26 | |
| 27 // PowerStatus::Observer overrides: | |
| 28 void OnPowerStatusChanged() override { ++power_changed_count_; } | |
| 29 | |
| 30 private: | |
| 31 int power_changed_count_; | |
| 32 | |
| 33 DISALLOW_COPY_AND_ASSIGN(TestObserver); | |
| 34 }; | |
| 35 | |
| 36 } // namespace | |
| 37 | |
| 38 class PowerStatusTest : public testing::Test { | |
| 39 public: | |
| 40 PowerStatusTest() : power_status_(NULL) {} | |
| 41 ~PowerStatusTest() override {} | |
| 42 | |
| 43 void SetUp() override { | |
| 44 chromeos::DBusThreadManager::Initialize(); | |
| 45 PowerStatus::Initialize(); | |
| 46 power_status_ = PowerStatus::Get(); | |
| 47 test_observer_.reset(new TestObserver); | |
| 48 power_status_->AddObserver(test_observer_.get()); | |
| 49 } | |
| 50 | |
| 51 void TearDown() override { | |
| 52 power_status_->RemoveObserver(test_observer_.get()); | |
| 53 test_observer_.reset(); | |
| 54 PowerStatus::Shutdown(); | |
| 55 chromeos::DBusThreadManager::Shutdown(); | |
| 56 } | |
| 57 | |
| 58 protected: | |
| 59 base::MessageLoopForUI message_loop_; | |
| 60 PowerStatus* power_status_; // Not owned. | |
| 61 std::unique_ptr<TestObserver> test_observer_; | |
| 62 | |
| 63 private: | |
| 64 DISALLOW_COPY_AND_ASSIGN(PowerStatusTest); | |
| 65 }; | |
| 66 | |
| 67 TEST_F(PowerStatusTest, InitializeAndUpdate) { | |
| 68 // Test that the initial power supply state should be acquired after | |
| 69 // PowerStatus is instantiated. This depends on | |
| 70 // PowerManagerClientStubImpl, which responds to power status update | |
| 71 // requests, pretends there is a battery present, and generates some valid | |
| 72 // power supply status data. | |
| 73 base::RunLoop().RunUntilIdle(); | |
| 74 EXPECT_EQ(1, test_observer_->power_changed_count()); | |
| 75 | |
| 76 // Test RequestUpdate, test_obsever_ should be notified for power suuply | |
| 77 // status change. | |
| 78 power_status_->RequestStatusUpdate(); | |
| 79 base::RunLoop().RunUntilIdle(); | |
| 80 EXPECT_EQ(2, test_observer_->power_changed_count()); | |
| 81 } | |
| 82 | |
| 83 TEST_F(PowerStatusTest, ShouldDisplayBatteryTime) { | |
| 84 EXPECT_FALSE( | |
| 85 PowerStatus::ShouldDisplayBatteryTime(base::TimeDelta::FromSeconds(-1))); | |
| 86 EXPECT_FALSE( | |
| 87 PowerStatus::ShouldDisplayBatteryTime(base::TimeDelta::FromSeconds(0))); | |
| 88 EXPECT_FALSE( | |
| 89 PowerStatus::ShouldDisplayBatteryTime(base::TimeDelta::FromSeconds(59))); | |
| 90 EXPECT_TRUE( | |
| 91 PowerStatus::ShouldDisplayBatteryTime(base::TimeDelta::FromSeconds(60))); | |
| 92 EXPECT_TRUE( | |
| 93 PowerStatus::ShouldDisplayBatteryTime(base::TimeDelta::FromSeconds(600))); | |
| 94 EXPECT_TRUE(PowerStatus::ShouldDisplayBatteryTime( | |
| 95 base::TimeDelta::FromSeconds(3600))); | |
| 96 EXPECT_TRUE(PowerStatus::ShouldDisplayBatteryTime( | |
| 97 base::TimeDelta::FromSeconds(PowerStatus::kMaxBatteryTimeToDisplaySec))); | |
| 98 EXPECT_FALSE( | |
| 99 PowerStatus::ShouldDisplayBatteryTime(base::TimeDelta::FromSeconds( | |
| 100 PowerStatus::kMaxBatteryTimeToDisplaySec + 1))); | |
| 101 } | |
| 102 | |
| 103 TEST_F(PowerStatusTest, SplitTimeIntoHoursAndMinutes) { | |
| 104 int hours = 0, minutes = 0; | |
| 105 PowerStatus::SplitTimeIntoHoursAndMinutes(base::TimeDelta::FromSeconds(0), | |
| 106 &hours, &minutes); | |
| 107 EXPECT_EQ(0, hours); | |
| 108 EXPECT_EQ(0, minutes); | |
| 109 | |
| 110 PowerStatus::SplitTimeIntoHoursAndMinutes(base::TimeDelta::FromSeconds(60), | |
| 111 &hours, &minutes); | |
| 112 EXPECT_EQ(0, hours); | |
| 113 EXPECT_EQ(1, minutes); | |
| 114 | |
| 115 PowerStatus::SplitTimeIntoHoursAndMinutes(base::TimeDelta::FromSeconds(3600), | |
| 116 &hours, &minutes); | |
| 117 EXPECT_EQ(1, hours); | |
| 118 EXPECT_EQ(0, minutes); | |
| 119 | |
| 120 PowerStatus::SplitTimeIntoHoursAndMinutes( | |
| 121 base::TimeDelta::FromSeconds(3600 + 60), &hours, &minutes); | |
| 122 EXPECT_EQ(1, hours); | |
| 123 EXPECT_EQ(1, minutes); | |
| 124 | |
| 125 PowerStatus::SplitTimeIntoHoursAndMinutes( | |
| 126 base::TimeDelta::FromSeconds(7 * 3600 + 23 * 60), &hours, &minutes); | |
| 127 EXPECT_EQ(7, hours); | |
| 128 EXPECT_EQ(23, minutes); | |
| 129 | |
| 130 // Check that minutes are rounded. | |
| 131 PowerStatus::SplitTimeIntoHoursAndMinutes( | |
| 132 base::TimeDelta::FromSeconds(2 * 3600 + 3 * 60 + 30), &hours, &minutes); | |
| 133 EXPECT_EQ(2, hours); | |
| 134 EXPECT_EQ(4, minutes); | |
| 135 | |
| 136 PowerStatus::SplitTimeIntoHoursAndMinutes( | |
| 137 base::TimeDelta::FromSeconds(2 * 3600 + 3 * 60 + 29), &hours, &minutes); | |
| 138 EXPECT_EQ(2, hours); | |
| 139 EXPECT_EQ(3, minutes); | |
| 140 | |
| 141 // Check that times close to hour boundaries aren't incorrectly rounded such | |
| 142 // that they display 60 minutes: http://crbug.com/368261 | |
| 143 PowerStatus::SplitTimeIntoHoursAndMinutes( | |
| 144 base::TimeDelta::FromSecondsD(3599.9), &hours, &minutes); | |
| 145 EXPECT_EQ(1, hours); | |
| 146 EXPECT_EQ(0, minutes); | |
| 147 | |
| 148 PowerStatus::SplitTimeIntoHoursAndMinutes( | |
| 149 base::TimeDelta::FromSecondsD(3600.1), &hours, &minutes); | |
| 150 EXPECT_EQ(1, hours); | |
| 151 EXPECT_EQ(0, minutes); | |
| 152 } | |
| 153 | |
| 154 TEST_F(PowerStatusTest, GetBatteryImageInfo) { | |
| 155 PowerSupplyProperties prop; | |
| 156 prop.set_external_power(PowerSupplyProperties::AC); | |
| 157 prop.set_battery_state(PowerSupplyProperties::CHARGING); | |
| 158 prop.set_battery_percent(98.0); | |
| 159 power_status_->SetProtoForTesting(prop); | |
| 160 const PowerStatus::BatteryImageInfo info_charging_98 = | |
| 161 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT); | |
| 162 | |
| 163 // 99% should use the same icon as 98%. | |
| 164 prop.set_battery_percent(99.0); | |
| 165 power_status_->SetProtoForTesting(prop); | |
| 166 EXPECT_EQ(info_charging_98, | |
| 167 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT)); | |
| 168 | |
| 169 // The dark icon set should use a different image for non-MD, but the | |
| 170 // same image for MD. | |
| 171 prop.set_battery_percent(98.0); | |
| 172 EXPECT_EQ(info_charging_98, | |
| 173 power_status_->GetBatteryImageInfo(PowerStatus::ICON_DARK)); | |
| 174 | |
| 175 // A different icon should be used when the battery is full, too. | |
| 176 prop.set_battery_state(PowerSupplyProperties::FULL); | |
| 177 prop.set_battery_percent(100.0); | |
| 178 power_status_->SetProtoForTesting(prop); | |
| 179 EXPECT_NE(info_charging_98, | |
| 180 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT)); | |
| 181 | |
| 182 // A much-lower battery level should use a different icon. | |
| 183 prop.set_battery_state(PowerSupplyProperties::CHARGING); | |
| 184 prop.set_battery_percent(20.0); | |
| 185 power_status_->SetProtoForTesting(prop); | |
| 186 EXPECT_NE(info_charging_98, | |
| 187 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT)); | |
| 188 | |
| 189 // Ditto for 98%, but on USB instead of AC. | |
| 190 prop.set_external_power(PowerSupplyProperties::USB); | |
| 191 prop.set_battery_percent(98.0); | |
| 192 power_status_->SetProtoForTesting(prop); | |
| 193 EXPECT_NE(info_charging_98, | |
| 194 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT)); | |
| 195 } | |
| 196 | |
| 197 // Tests that the |icon_badge| member of BatteryImageInfo is set correctly | |
| 198 // with various power supply property values. | |
| 199 TEST_F(PowerStatusTest, BatteryImageInfoIconBadge) { | |
| 200 PowerSupplyProperties prop; | |
| 201 | |
| 202 // A charging battery connected to AC power should have an ICON_BADGE_BOLT. | |
| 203 prop.set_external_power(PowerSupplyProperties::AC); | |
| 204 prop.set_battery_state(PowerSupplyProperties::CHARGING); | |
| 205 prop.set_battery_percent(98.0); | |
| 206 power_status_->SetProtoForTesting(prop); | |
| 207 EXPECT_EQ( | |
| 208 PowerStatus::ICON_BADGE_BOLT, | |
| 209 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).icon_badge); | |
| 210 | |
| 211 // A discharging battery connected to AC should also have an ICON_BADGE_BOLT. | |
| 212 prop.set_battery_state(PowerSupplyProperties::DISCHARGING); | |
| 213 power_status_->SetProtoForTesting(prop); | |
| 214 EXPECT_EQ( | |
| 215 PowerStatus::ICON_BADGE_BOLT, | |
| 216 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).icon_badge); | |
| 217 | |
| 218 // A charging battery connected to USB power should have an | |
| 219 // ICON_BADGE_UNRELIABLE. | |
| 220 prop.set_external_power(PowerSupplyProperties::USB); | |
| 221 prop.set_battery_state(PowerSupplyProperties::CHARGING); | |
| 222 power_status_->SetProtoForTesting(prop); | |
| 223 EXPECT_EQ( | |
| 224 PowerStatus::ICON_BADGE_UNRELIABLE, | |
| 225 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).icon_badge); | |
| 226 | |
| 227 // A discharging battery connected to USB power should also have an | |
| 228 // ICON_BADGE_UNRELIABLE. | |
| 229 prop.set_battery_state(PowerSupplyProperties::DISCHARGING); | |
| 230 power_status_->SetProtoForTesting(prop); | |
| 231 EXPECT_EQ( | |
| 232 PowerStatus::ICON_BADGE_UNRELIABLE, | |
| 233 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).icon_badge); | |
| 234 | |
| 235 // Show an ICON_BADGE_X when no battery is present. | |
| 236 prop.set_external_power(PowerSupplyProperties::DISCONNECTED); | |
| 237 prop.set_battery_state(PowerSupplyProperties::NOT_PRESENT); | |
| 238 power_status_->SetProtoForTesting(prop); | |
| 239 EXPECT_EQ( | |
| 240 PowerStatus::ICON_BADGE_X, | |
| 241 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).icon_badge); | |
| 242 | |
| 243 // Do not show a badge when the battery is discharging. | |
| 244 prop.set_battery_state(PowerSupplyProperties::DISCHARGING); | |
| 245 power_status_->SetProtoForTesting(prop); | |
| 246 EXPECT_EQ( | |
| 247 PowerStatus::ICON_BADGE_NONE, | |
| 248 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).icon_badge); | |
| 249 | |
| 250 // Show ICON_BADGE_ALERT for a discharging battery when it falls below | |
| 251 // a charge level of PowerStatus::kCriticalBatteryChargePercentageMd. | |
| 252 prop.set_battery_percent(PowerStatus::kCriticalBatteryChargePercentageMd); | |
| 253 power_status_->SetProtoForTesting(prop); | |
| 254 EXPECT_EQ( | |
| 255 PowerStatus::ICON_BADGE_NONE, | |
| 256 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).icon_badge); | |
| 257 prop.set_battery_percent(PowerStatus::kCriticalBatteryChargePercentageMd - 1); | |
| 258 power_status_->SetProtoForTesting(prop); | |
| 259 EXPECT_EQ( | |
| 260 PowerStatus::ICON_BADGE_ALERT, | |
| 261 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).icon_badge); | |
| 262 } | |
| 263 | |
| 264 // Tests that the |charge_level| member of BatteryImageInfo is set correctly | |
| 265 // with various power supply property values. | |
| 266 TEST_F(PowerStatusTest, BatteryImageInfoChargeLevel) { | |
| 267 PowerSupplyProperties prop; | |
| 268 | |
| 269 // No charge level is drawn when the battery is not present. | |
| 270 prop.set_external_power(PowerSupplyProperties::DISCONNECTED); | |
| 271 prop.set_battery_state(PowerSupplyProperties::NOT_PRESENT); | |
| 272 power_status_->SetProtoForTesting(prop); | |
| 273 EXPECT_EQ( | |
| 274 0, | |
| 275 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).charge_level); | |
| 276 | |
| 277 // A charge level of 0 when the battery is 0% full. | |
| 278 prop.set_external_power(PowerSupplyProperties::AC); | |
| 279 prop.set_battery_state(PowerSupplyProperties::CHARGING); | |
| 280 prop.set_battery_percent(0.0); | |
| 281 EXPECT_EQ( | |
| 282 0, | |
| 283 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).charge_level); | |
| 284 | |
| 285 // A charge level of 1 when the battery is up to 16% full, and a level of 2 | |
| 286 // for 17% full. | |
| 287 prop.set_battery_percent(16.0); | |
| 288 power_status_->SetProtoForTesting(prop); | |
| 289 EXPECT_EQ( | |
| 290 1, | |
| 291 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).charge_level); | |
| 292 prop.set_battery_percent(17.0); | |
| 293 power_status_->SetProtoForTesting(prop); | |
| 294 EXPECT_EQ( | |
| 295 2, | |
| 296 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).charge_level); | |
| 297 | |
| 298 // A charge level of 6 when the battery is 50% full. | |
| 299 prop.set_battery_percent(50.0); | |
| 300 power_status_->SetProtoForTesting(prop); | |
| 301 EXPECT_EQ( | |
| 302 6, | |
| 303 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).charge_level); | |
| 304 | |
| 305 // A charge level of 11 when the battery is 99% full, and a level of 12 when | |
| 306 // the battery is 100% full. | |
| 307 prop.set_battery_percent(99.0); | |
| 308 power_status_->SetProtoForTesting(prop); | |
| 309 EXPECT_EQ( | |
| 310 11, | |
| 311 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).charge_level); | |
| 312 prop.set_battery_percent(100.0); | |
| 313 power_status_->SetProtoForTesting(prop); | |
| 314 EXPECT_EQ( | |
| 315 12, | |
| 316 power_status_->GetBatteryImageInfo(PowerStatus::ICON_LIGHT).charge_level); | |
| 317 } | |
| 318 | |
| 319 } // namespace ash | |
| OLD | NEW |