device_status_collector_browsertest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright (c) 2012 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 "chrome/browser/chromeos/policy/device_status_collector.h" 6 7#include "base/environment.h" 8#include "base/logging.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/message_loop.h" 11#include "base/prefs/pref_service.h" 12#include "base/prefs/testing_pref_service.h" 13#include "base/threading/sequenced_worker_pool.h" 14#include "chrome/browser/chromeos/settings/cros_settings.h" 15#include "chrome/browser/chromeos/settings/cros_settings_names.h" 16#include "chrome/browser/chromeos/settings/cros_settings_provider.h" 17#include "chrome/browser/chromeos/settings/device_settings_service.h" 18#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" 19#include "chrome/browser/chromeos/system/mock_statistics_provider.h" 20#include "chrome/browser/chromeos/system/statistics_provider.h" 21#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" 22#include "chrome/common/pref_names.h" 23#include "content/public/browser/browser_thread.h" 24#include "content/public/browser/geolocation_provider.h" 25#include "content/public/test/test_browser_thread.h" 26#include "content/public/test/test_utils.h" 27#include "testing/gmock/include/gmock/gmock.h" 28#include "testing/gtest/include/gtest/gtest.h" 29 30using ::testing::DoAll; 31using ::testing::NotNull; 32using ::testing::Return; 33using ::testing::SetArgPointee; 34using ::testing::_; 35using base::Time; 36using base::TimeDelta; 37 38namespace em = enterprise_management; 39 40namespace { 41 42const int64 kMillisecondsPerDay = Time::kMicrosecondsPerDay / 1000; 43 44scoped_ptr<content::Geoposition> mock_position_to_return_next; 45 46void SetMockPositionToReturnNext(const content::Geoposition &position) { 47 mock_position_to_return_next.reset(new content::Geoposition(position)); 48} 49 50void MockPositionUpdateRequester( 51 const content::GeolocationProvider::LocationUpdateCallback& callback) { 52 if (!mock_position_to_return_next.get()) 53 return; 54 55 // If the fix is invalid, the DeviceStatusCollector will immediately request 56 // another update when it receives the callback. This is desirable and safe in 57 // real life where geolocation updates arrive asynchronously. In this testing 58 // harness, the callback is invoked synchronously upon request, leading to a 59 // request-callback loop. The loop is broken by returning the mock position 60 // only once. 61 scoped_ptr<content::Geoposition> position( 62 mock_position_to_return_next.release()); 63 callback.Run(*position); 64} 65 66class TestingDeviceStatusCollector : public policy::DeviceStatusCollector { 67 public: 68 TestingDeviceStatusCollector( 69 PrefService* local_state, 70 chromeos::system::StatisticsProvider* provider, 71 policy::DeviceStatusCollector::LocationUpdateRequester* 72 location_update_requester) 73 : policy::DeviceStatusCollector( 74 local_state, 75 provider, 76 location_update_requester) { 77 // Set the baseline time to a fixed value (1 AM) to prevent test flakiness 78 // due to a single activity period spanning two days. 79 SetBaselineTime(Time::Now().LocalMidnight() + TimeDelta::FromHours(1)); 80 } 81 82 void Simulate(IdleState* states, int len) { 83 for (int i = 0; i < len; i++) 84 IdleStateCallback(states[i]); 85 } 86 87 void set_max_stored_past_activity_days(unsigned int value) { 88 max_stored_past_activity_days_ = value; 89 } 90 91 void set_max_stored_future_activity_days(unsigned int value) { 92 max_stored_future_activity_days_ = value; 93 } 94 95 // Reset the baseline time. 96 void SetBaselineTime(Time time) { 97 baseline_time_ = time; 98 baseline_offset_periods_ = 0; 99 } 100 101 protected: 102 virtual void CheckIdleState() OVERRIDE { 103 // This should never be called in testing, as it results in a dbus call. 104 ADD_FAILURE(); 105 } 106 107 // Each time this is called, returns a time that is a fixed increment 108 // later than the previous time. 109 virtual Time GetCurrentTime() OVERRIDE { 110 int poll_interval = policy::DeviceStatusCollector::kIdlePollIntervalSeconds; 111 return baseline_time_ + 112 TimeDelta::FromSeconds(poll_interval * baseline_offset_periods_++); 113 } 114 115 private: 116 // Baseline time for the fake times returned from GetCurrentTime(). 117 Time baseline_time_; 118 119 // The number of simulated periods since the baseline time. 120 int baseline_offset_periods_; 121}; 122 123// Return the total number of active milliseconds contained in a device 124// status report. 125int64 GetActiveMilliseconds(em::DeviceStatusReportRequest& status) { 126 int64 active_milliseconds = 0; 127 for (int i = 0; i < status.active_period_size(); i++) { 128 active_milliseconds += status.active_period(i).active_duration(); 129 } 130 return active_milliseconds; 131} 132 133} // namespace 134 135namespace policy { 136 137// Though it is a unit test, this test is linked with browser_tests so that it 138// runs in a separate process. The intention is to avoid overriding the timezone 139// environment variable for other tests. 140class DeviceStatusCollectorTest : public testing::Test { 141 public: 142 DeviceStatusCollectorTest() 143 : message_loop_(base::MessageLoop::TYPE_UI), 144 ui_thread_(content::BrowserThread::UI, &message_loop_), 145 file_thread_(content::BrowserThread::FILE, &message_loop_), 146 io_thread_(content::BrowserThread::IO, &message_loop_) { 147 // Run this test with a well-known timezone so that Time::LocalMidnight() 148 // returns the same values on all machines. 149 scoped_ptr<base::Environment> env(base::Environment::Create()); 150 env->SetVar("TZ", "UTC"); 151 152 TestingDeviceStatusCollector::RegisterPrefs(prefs_.registry()); 153 154 EXPECT_CALL(statistics_provider_, GetMachineStatistic(_, NotNull())) 155 .WillRepeatedly(Return(false)); 156 157 // Remove the real DeviceSettingsProvider and replace it with a stub. 158 cros_settings_ = chromeos::CrosSettings::Get(); 159 device_settings_provider_ = 160 cros_settings_->GetProvider(chromeos::kReportDeviceVersionInfo); 161 EXPECT_TRUE(device_settings_provider_ != NULL); 162 EXPECT_TRUE( 163 cros_settings_->RemoveSettingsProvider(device_settings_provider_)); 164 cros_settings_->AddSettingsProvider(&stub_settings_provider_); 165 166 RestartStatusCollector(); 167 } 168 169 virtual ~DeviceStatusCollectorTest() { 170 // Finish pending tasks. 171 content::BrowserThread::GetBlockingPool()->FlushForTesting(); 172 message_loop_.RunUntilIdle(); 173 174 // Restore the real DeviceSettingsProvider. 175 EXPECT_TRUE( 176 cros_settings_->RemoveSettingsProvider(&stub_settings_provider_)); 177 cros_settings_->AddSettingsProvider(device_settings_provider_); 178 } 179 180 void RestartStatusCollector() { 181 policy::DeviceStatusCollector::LocationUpdateRequester callback = 182 base::Bind(&MockPositionUpdateRequester); 183 status_collector_.reset( 184 new TestingDeviceStatusCollector(&prefs_, 185 &statistics_provider_, 186 &callback)); 187 } 188 189 void GetStatus() { 190 status_.Clear(); 191 status_collector_->GetDeviceStatus(&status_); 192 } 193 194 void CheckThatNoLocationIsReported() { 195 GetStatus(); 196 EXPECT_FALSE(status_.has_device_location()); 197 } 198 199 void CheckThatAValidLocationIsReported() { 200 // Checks that a location is being reported which matches the valid fix 201 // set using SetMockPositionToReturnNext(). 202 GetStatus(); 203 EXPECT_TRUE(status_.has_device_location()); 204 em::DeviceLocation location = status_.device_location(); 205 if (location.has_error_code()) 206 EXPECT_EQ(em::DeviceLocation::ERROR_CODE_NONE, location.error_code()); 207 EXPECT_TRUE(location.has_latitude()); 208 EXPECT_TRUE(location.has_longitude()); 209 EXPECT_TRUE(location.has_accuracy()); 210 EXPECT_TRUE(location.has_timestamp()); 211 EXPECT_FALSE(location.has_altitude()); 212 EXPECT_FALSE(location.has_altitude_accuracy()); 213 EXPECT_FALSE(location.has_heading()); 214 EXPECT_FALSE(location.has_speed()); 215 EXPECT_FALSE(location.has_error_message()); 216 EXPECT_DOUBLE_EQ(4.3, location.latitude()); 217 EXPECT_DOUBLE_EQ(-7.8, location.longitude()); 218 EXPECT_DOUBLE_EQ(3., location.accuracy()); 219 // Check that the timestamp is not older than ten minutes. 220 EXPECT_TRUE(Time::Now() - Time::FromDoubleT(location.timestamp() / 1000.) < 221 TimeDelta::FromMinutes(10)); 222 } 223 224 void CheckThatALocationErrorIsReported() { 225 GetStatus(); 226 EXPECT_TRUE(status_.has_device_location()); 227 em::DeviceLocation location = status_.device_location(); 228 EXPECT_TRUE(location.has_error_code()); 229 EXPECT_EQ(em::DeviceLocation::ERROR_CODE_POSITION_UNAVAILABLE, 230 location.error_code()); 231 } 232 233 protected: 234 // Convenience method. 235 int64 ActivePeriodMilliseconds() { 236 return policy::DeviceStatusCollector::kIdlePollIntervalSeconds * 1000; 237 } 238 239 base::MessageLoop message_loop_; 240 content::TestBrowserThread ui_thread_; 241 content::TestBrowserThread file_thread_; 242 content::TestBrowserThread io_thread_; 243 244 TestingPrefServiceSimple prefs_; 245 chromeos::system::MockStatisticsProvider statistics_provider_; 246 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 247 chromeos::ScopedTestCrosSettings test_cros_settings_; 248 chromeos::CrosSettings* cros_settings_; 249 chromeos::CrosSettingsProvider* device_settings_provider_; 250 chromeos::StubCrosSettingsProvider stub_settings_provider_; 251 em::DeviceStatusReportRequest status_; 252 scoped_ptr<TestingDeviceStatusCollector> status_collector_; 253}; 254 255TEST_F(DeviceStatusCollectorTest, AllIdle) { 256 IdleState test_states[] = { 257 IDLE_STATE_IDLE, 258 IDLE_STATE_IDLE, 259 IDLE_STATE_IDLE 260 }; 261 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 262 263 // Test reporting with no data. 264 GetStatus(); 265 EXPECT_EQ(0, status_.active_period_size()); 266 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 267 268 // Test reporting with a single idle sample. 269 status_collector_->Simulate(test_states, 1); 270 GetStatus(); 271 EXPECT_EQ(0, status_.active_period_size()); 272 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 273 274 // Test reporting with multiple consecutive idle samples. 275 status_collector_->Simulate(test_states, 276 sizeof(test_states) / sizeof(IdleState)); 277 GetStatus(); 278 EXPECT_EQ(0, status_.active_period_size()); 279 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 280} 281 282TEST_F(DeviceStatusCollectorTest, AllActive) { 283 IdleState test_states[] = { 284 IDLE_STATE_ACTIVE, 285 IDLE_STATE_ACTIVE, 286 IDLE_STATE_ACTIVE 287 }; 288 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 289 290 // Test a single active sample. 291 status_collector_->Simulate(test_states, 1); 292 GetStatus(); 293 EXPECT_EQ(1, status_.active_period_size()); 294 EXPECT_EQ(1 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 295 status_.clear_active_period(); // Clear the result protobuf. 296 297 // Test multiple consecutive active samples. 298 status_collector_->Simulate(test_states, 299 sizeof(test_states) / sizeof(IdleState)); 300 GetStatus(); 301 EXPECT_EQ(1, status_.active_period_size()); 302 EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 303} 304 305TEST_F(DeviceStatusCollectorTest, MixedStates) { 306 IdleState test_states[] = { 307 IDLE_STATE_ACTIVE, 308 IDLE_STATE_IDLE, 309 IDLE_STATE_ACTIVE, 310 IDLE_STATE_ACTIVE, 311 IDLE_STATE_IDLE, 312 IDLE_STATE_IDLE, 313 IDLE_STATE_ACTIVE 314 }; 315 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 316 status_collector_->Simulate(test_states, 317 sizeof(test_states) / sizeof(IdleState)); 318 GetStatus(); 319 EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 320} 321 322TEST_F(DeviceStatusCollectorTest, StateKeptInPref) { 323 IdleState test_states[] = { 324 IDLE_STATE_ACTIVE, 325 IDLE_STATE_IDLE, 326 IDLE_STATE_ACTIVE, 327 IDLE_STATE_ACTIVE, 328 IDLE_STATE_IDLE, 329 IDLE_STATE_IDLE 330 }; 331 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 332 status_collector_->Simulate(test_states, 333 sizeof(test_states) / sizeof(IdleState)); 334 335 // Process the list a second time after restarting the collector. It should be 336 // able to count the active periods found by the original collector, because 337 // the results are stored in a pref. 338 RestartStatusCollector(); 339 status_collector_->Simulate(test_states, 340 sizeof(test_states) / sizeof(IdleState)); 341 342 GetStatus(); 343 EXPECT_EQ(6 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 344} 345 346TEST_F(DeviceStatusCollectorTest, Times) { 347 IdleState test_states[] = { 348 IDLE_STATE_ACTIVE, 349 IDLE_STATE_IDLE, 350 IDLE_STATE_ACTIVE, 351 IDLE_STATE_ACTIVE, 352 IDLE_STATE_IDLE, 353 IDLE_STATE_IDLE 354 }; 355 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 356 status_collector_->Simulate(test_states, 357 sizeof(test_states) / sizeof(IdleState)); 358 GetStatus(); 359 EXPECT_EQ(3 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 360} 361 362TEST_F(DeviceStatusCollectorTest, MaxStoredPeriods) { 363 IdleState test_states[] = { 364 IDLE_STATE_ACTIVE, 365 IDLE_STATE_IDLE 366 }; 367 const int kMaxDays = 10; 368 369 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 370 status_collector_->set_max_stored_past_activity_days(kMaxDays - 1); 371 status_collector_->set_max_stored_future_activity_days(1); 372 Time baseline = Time::Now().LocalMidnight(); 373 374 // Simulate 12 active periods. 375 for (int i = 0; i < kMaxDays + 2; i++) { 376 status_collector_->Simulate(test_states, 377 sizeof(test_states) / sizeof(IdleState)); 378 // Advance the simulated clock by a day. 379 baseline += TimeDelta::FromDays(1); 380 status_collector_->SetBaselineTime(baseline); 381 } 382 383 // Check that we don't exceed the max number of periods. 384 GetStatus(); 385 EXPECT_EQ(kMaxDays - 1, status_.active_period_size()); 386 387 // Simulate some future times. 388 for (int i = 0; i < kMaxDays + 2; i++) { 389 status_collector_->Simulate(test_states, 390 sizeof(test_states) / sizeof(IdleState)); 391 // Advance the simulated clock by a day. 392 baseline += TimeDelta::FromDays(1); 393 status_collector_->SetBaselineTime(baseline); 394 } 395 // Set the clock back so the previous simulated times are in the future. 396 baseline -= TimeDelta::FromDays(20); 397 status_collector_->SetBaselineTime(baseline); 398 399 // Collect one more data point to trigger pruning. 400 status_collector_->Simulate(test_states, 1); 401 402 // Check that we don't exceed the max number of periods. 403 status_.clear_active_period(); 404 GetStatus(); 405 EXPECT_LT(status_.active_period_size(), kMaxDays); 406} 407 408TEST_F(DeviceStatusCollectorTest, ActivityTimesDisabledByDefault) { 409 // If the pref for collecting device activity times isn't explicitly turned 410 // on, no data on activity times should be reported. 411 412 IdleState test_states[] = { 413 IDLE_STATE_ACTIVE, 414 IDLE_STATE_ACTIVE, 415 IDLE_STATE_ACTIVE 416 }; 417 status_collector_->Simulate(test_states, 418 sizeof(test_states) / sizeof(IdleState)); 419 GetStatus(); 420 EXPECT_EQ(0, status_.active_period_size()); 421 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 422} 423 424TEST_F(DeviceStatusCollectorTest, ActivityCrossingMidnight) { 425 IdleState test_states[] = { 426 IDLE_STATE_ACTIVE 427 }; 428 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 429 430 // Set the baseline time to 10 seconds after midnight. 431 status_collector_->SetBaselineTime( 432 Time::Now().LocalMidnight() + TimeDelta::FromSeconds(10)); 433 434 status_collector_->Simulate(test_states, 1); 435 GetStatus(); 436 ASSERT_EQ(2, status_.active_period_size()); 437 438 em::ActiveTimePeriod period0 = status_.active_period(0); 439 em::ActiveTimePeriod period1 = status_.active_period(1); 440 EXPECT_EQ(ActivePeriodMilliseconds() - 10000, period0.active_duration()); 441 EXPECT_EQ(10000, period1.active_duration()); 442 443 em::TimePeriod time_period0 = period0.time_period(); 444 em::TimePeriod time_period1 = period1.time_period(); 445 446 EXPECT_EQ(time_period0.end_timestamp(), time_period1.start_timestamp()); 447 448 // Ensure that the start and end times for the period are a day apart. 449 EXPECT_EQ(time_period0.end_timestamp() - time_period0.start_timestamp(), 450 kMillisecondsPerDay); 451 EXPECT_EQ(time_period1.end_timestamp() - time_period1.start_timestamp(), 452 kMillisecondsPerDay); 453} 454 455TEST_F(DeviceStatusCollectorTest, ActivityTimesKeptUntilSubmittedSuccessfully) { 456 IdleState test_states[] = { 457 IDLE_STATE_ACTIVE, 458 IDLE_STATE_ACTIVE, 459 }; 460 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 461 462 status_collector_->Simulate(test_states, 2); 463 GetStatus(); 464 EXPECT_EQ(2 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 465 em::DeviceStatusReportRequest first_status(status_); 466 467 // The collector returns the same status again. 468 GetStatus(); 469 EXPECT_EQ(first_status.SerializeAsString(), status_.SerializeAsString()); 470 471 // After indicating a successful submit, the submitted status gets cleared, 472 // but what got collected meanwhile sticks around. 473 status_collector_->Simulate(test_states, 1); 474 status_collector_->OnSubmittedSuccessfully(); 475 GetStatus(); 476 EXPECT_EQ(ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 477} 478 479TEST_F(DeviceStatusCollectorTest, DevSwitchBootMode) { 480 // Test that boot mode data is not reported if the pref is not turned on. 481 EXPECT_CALL(statistics_provider_, 482 GetMachineStatistic("devsw_boot", NotNull())) 483 .WillRepeatedly(DoAll(SetArgPointee<1>("0"), Return(true))); 484 GetStatus(); 485 EXPECT_FALSE(status_.has_boot_mode()); 486 487 // Turn the pref on, and check that the status is reported iff the 488 // statistics provider returns valid data. 489 cros_settings_->SetBoolean(chromeos::kReportDeviceBootMode, true); 490 491 EXPECT_CALL(statistics_provider_, 492 GetMachineStatistic("devsw_boot", NotNull())) 493 .WillOnce(DoAll(SetArgPointee<1>("(error)"), Return(true))); 494 GetStatus(); 495 EXPECT_FALSE(status_.has_boot_mode()); 496 497 EXPECT_CALL(statistics_provider_, 498 GetMachineStatistic("devsw_boot", NotNull())) 499 .WillOnce(DoAll(SetArgPointee<1>(" "), Return(true))); 500 GetStatus(); 501 EXPECT_FALSE(status_.has_boot_mode()); 502 503 EXPECT_CALL(statistics_provider_, 504 GetMachineStatistic("devsw_boot", NotNull())) 505 .WillOnce(DoAll(SetArgPointee<1>("0"), Return(true))); 506 GetStatus(); 507 EXPECT_EQ("Verified", status_.boot_mode()); 508 509 EXPECT_CALL(statistics_provider_, 510 GetMachineStatistic("devsw_boot", NotNull())) 511 .WillOnce(DoAll(SetArgPointee<1>("1"), Return(true))); 512 GetStatus(); 513 EXPECT_EQ("Dev", status_.boot_mode()); 514} 515 516TEST_F(DeviceStatusCollectorTest, VersionInfo) { 517 // When the pref to collect this data is not enabled, expect that none of 518 // the fields are present in the protobuf. 519 GetStatus(); 520 EXPECT_FALSE(status_.has_browser_version()); 521 EXPECT_FALSE(status_.has_os_version()); 522 EXPECT_FALSE(status_.has_firmware_version()); 523 524 cros_settings_->SetBoolean(chromeos::kReportDeviceVersionInfo, true); 525 GetStatus(); 526 EXPECT_TRUE(status_.has_browser_version()); 527 EXPECT_TRUE(status_.has_os_version()); 528 EXPECT_TRUE(status_.has_firmware_version()); 529 530 // Check that the browser version is not empty. OS version & firmware 531 // don't have any reasonable values inside the unit test, so those 532 // aren't checked. 533 EXPECT_NE("", status_.browser_version()); 534} 535 536TEST_F(DeviceStatusCollectorTest, Location) { 537 content::Geoposition valid_fix; 538 valid_fix.latitude = 4.3; 539 valid_fix.longitude = -7.8; 540 valid_fix.accuracy = 3.; 541 valid_fix.timestamp = Time::Now(); 542 543 content::Geoposition invalid_fix; 544 invalid_fix.error_code = 545 content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 546 invalid_fix.timestamp = Time::Now(); 547 548 // Check that when device location reporting is disabled, no location is 549 // reported. 550 SetMockPositionToReturnNext(valid_fix); 551 CheckThatNoLocationIsReported(); 552 553 // Check that when device location reporting is enabled and a valid fix is 554 // available, the location is reported and is stored in local state. 555 SetMockPositionToReturnNext(valid_fix); 556 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); 557 EXPECT_FALSE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); 558 CheckThatAValidLocationIsReported(); 559 560 // Restart the status collector. Check that the last known location has been 561 // retrieved from local state without requesting a geolocation update. 562 SetMockPositionToReturnNext(valid_fix); 563 RestartStatusCollector(); 564 CheckThatAValidLocationIsReported(); 565 EXPECT_TRUE(mock_position_to_return_next.get()); 566 567 // Check that after disabling location reporting again, the last known 568 // location has been cleared from local state and is no longer reported. 569 SetMockPositionToReturnNext(valid_fix); 570 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, false); 571 // Allow the new pref to propagate to the status collector. 572 message_loop_.RunUntilIdle(); 573 EXPECT_TRUE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); 574 CheckThatNoLocationIsReported(); 575 576 // Check that after enabling location reporting again, an error is reported 577 // if no valid fix is available. 578 SetMockPositionToReturnNext(invalid_fix); 579 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); 580 // Allow the new pref to propagate to the status collector. 581 message_loop_.RunUntilIdle(); 582 CheckThatALocationErrorIsReported(); 583} 584 585} // namespace policy 586