device_status_collector_browsertest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/message_loop.h" 11#include "base/prefs/pref_service.h" 12#include "base/prefs/testing_pref_service.h" 13#include "base/run_loop.h" 14#include "base/threading/sequenced_worker_pool.h" 15#include "chrome/browser/chromeos/login/mock_user_manager.h" 16#include "chrome/browser/chromeos/login/user_manager.h" 17#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 18#include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h" 19#include "chrome/browser/chromeos/settings/cros_settings.h" 20#include "chrome/browser/chromeos/settings/device_settings_service.h" 21#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" 22#include "chrome/common/pref_names.h" 23#include "chrome/test/base/testing_browser_process.h" 24#include "chromeos/dbus/dbus_thread_manager.h" 25#include "chromeos/dbus/shill_device_client.h" 26#include "chromeos/network/network_handler.h" 27#include "chromeos/settings/cros_settings_names.h" 28#include "chromeos/settings/cros_settings_provider.h" 29#include "chromeos/system/mock_statistics_provider.h" 30#include "content/public/browser/browser_thread.h" 31#include "content/public/browser/geolocation_provider.h" 32#include "content/public/test/test_browser_thread.h" 33#include "content/public/test/test_utils.h" 34#include "policy/proto/device_management_backend.pb.h" 35#include "testing/gmock/include/gmock/gmock.h" 36#include "testing/gtest/include/gtest/gtest.h" 37#include "third_party/cros_system_api/dbus/service_constants.h" 38 39using ::testing::DoAll; 40using ::testing::NotNull; 41using ::testing::Return; 42using ::testing::SetArgPointee; 43using ::testing::_; 44using base::Time; 45using base::TimeDelta; 46 47namespace em = enterprise_management; 48 49namespace { 50 51const int64 kMillisecondsPerDay = Time::kMicrosecondsPerDay / 1000; 52 53scoped_ptr<content::Geoposition> mock_position_to_return_next; 54 55void SetMockPositionToReturnNext(const content::Geoposition &position) { 56 mock_position_to_return_next.reset(new content::Geoposition(position)); 57} 58 59void MockPositionUpdateRequester( 60 const content::GeolocationProvider::LocationUpdateCallback& callback) { 61 if (!mock_position_to_return_next.get()) 62 return; 63 64 // If the fix is invalid, the DeviceStatusCollector will immediately request 65 // another update when it receives the callback. This is desirable and safe in 66 // real life where geolocation updates arrive asynchronously. In this testing 67 // harness, the callback is invoked synchronously upon request, leading to a 68 // request-callback loop. The loop is broken by returning the mock position 69 // only once. 70 scoped_ptr<content::Geoposition> position( 71 mock_position_to_return_next.release()); 72 callback.Run(*position); 73} 74 75class TestingDeviceStatusCollector : public policy::DeviceStatusCollector { 76 public: 77 TestingDeviceStatusCollector( 78 PrefService* local_state, 79 chromeos::system::StatisticsProvider* provider, 80 policy::DeviceStatusCollector::LocationUpdateRequester* 81 location_update_requester) 82 : policy::DeviceStatusCollector( 83 local_state, 84 provider, 85 location_update_requester) { 86 // Set the baseline time to a fixed value (1 AM) to prevent test flakiness 87 // due to a single activity period spanning two days. 88 SetBaselineTime(Time::Now().LocalMidnight() + TimeDelta::FromHours(1)); 89 } 90 91 void Simulate(IdleState* states, int len) { 92 for (int i = 0; i < len; i++) 93 IdleStateCallback(states[i]); 94 } 95 96 void set_max_stored_past_activity_days(unsigned int value) { 97 max_stored_past_activity_days_ = value; 98 } 99 100 void set_max_stored_future_activity_days(unsigned int value) { 101 max_stored_future_activity_days_ = value; 102 } 103 104 // Reset the baseline time. 105 void SetBaselineTime(Time time) { 106 baseline_time_ = time; 107 baseline_offset_periods_ = 0; 108 } 109 110 protected: 111 virtual void CheckIdleState() OVERRIDE { 112 // This should never be called in testing, as it results in a dbus call. 113 ADD_FAILURE(); 114 } 115 116 // Each time this is called, returns a time that is a fixed increment 117 // later than the previous time. 118 virtual Time GetCurrentTime() OVERRIDE { 119 int poll_interval = policy::DeviceStatusCollector::kIdlePollIntervalSeconds; 120 return baseline_time_ + 121 TimeDelta::FromSeconds(poll_interval * baseline_offset_periods_++); 122 } 123 124 private: 125 // Baseline time for the fake times returned from GetCurrentTime(). 126 Time baseline_time_; 127 128 // The number of simulated periods since the baseline time. 129 int baseline_offset_periods_; 130}; 131 132// Return the total number of active milliseconds contained in a device 133// status report. 134int64 GetActiveMilliseconds(em::DeviceStatusReportRequest& status) { 135 int64 active_milliseconds = 0; 136 for (int i = 0; i < status.active_period_size(); i++) { 137 active_milliseconds += status.active_period(i).active_duration(); 138 } 139 return active_milliseconds; 140} 141 142} // namespace 143 144namespace policy { 145 146// Though it is a unit test, this test is linked with browser_tests so that it 147// runs in a separate process. The intention is to avoid overriding the timezone 148// environment variable for other tests. 149class DeviceStatusCollectorTest : public testing::Test { 150 public: 151 DeviceStatusCollectorTest() 152 : ui_thread_(content::BrowserThread::UI, &message_loop_), 153 file_thread_(content::BrowserThread::FILE, &message_loop_), 154 io_thread_(content::BrowserThread::IO, &message_loop_), 155 user_manager_(new chromeos::MockUserManager()), 156 user_manager_enabler_(user_manager_) { 157 // Run this test with a well-known timezone so that Time::LocalMidnight() 158 // returns the same values on all machines. 159 scoped_ptr<base::Environment> env(base::Environment::Create()); 160 env->SetVar("TZ", "UTC"); 161 162 TestingDeviceStatusCollector::RegisterPrefs(prefs_.registry()); 163 164 EXPECT_CALL(statistics_provider_, GetMachineStatistic(_, NotNull())) 165 .WillRepeatedly(Return(false)); 166 167 // Remove the real DeviceSettingsProvider and replace it with a stub. 168 cros_settings_ = chromeos::CrosSettings::Get(); 169 device_settings_provider_ = 170 cros_settings_->GetProvider(chromeos::kReportDeviceVersionInfo); 171 EXPECT_TRUE(device_settings_provider_ != NULL); 172 EXPECT_TRUE( 173 cros_settings_->RemoveSettingsProvider(device_settings_provider_)); 174 cros_settings_->AddSettingsProvider(&stub_settings_provider_); 175 176 // Set up fake install attributes. 177 StubEnterpriseInstallAttributes* attributes = 178 new StubEnterpriseInstallAttributes(); 179 attributes->SetDomain("managed.com"); 180 attributes->SetRegistrationUser("user@managed.com"); 181 BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(attributes); 182 183 RestartStatusCollector(); 184 } 185 186 virtual ~DeviceStatusCollectorTest() { 187 // Finish pending tasks. 188 content::BrowserThread::GetBlockingPool()->FlushForTesting(); 189 message_loop_.RunUntilIdle(); 190 191 // Restore the real DeviceSettingsProvider. 192 EXPECT_TRUE( 193 cros_settings_->RemoveSettingsProvider(&stub_settings_provider_)); 194 cros_settings_->AddSettingsProvider(device_settings_provider_); 195 } 196 197 void RestartStatusCollector() { 198 policy::DeviceStatusCollector::LocationUpdateRequester callback = 199 base::Bind(&MockPositionUpdateRequester); 200 status_collector_.reset( 201 new TestingDeviceStatusCollector(&prefs_, 202 &statistics_provider_, 203 &callback)); 204 } 205 206 void GetStatus() { 207 status_.Clear(); 208 status_collector_->GetDeviceStatus(&status_); 209 } 210 211 void CheckThatNoLocationIsReported() { 212 GetStatus(); 213 EXPECT_FALSE(status_.has_device_location()); 214 } 215 216 void CheckThatAValidLocationIsReported() { 217 // Checks that a location is being reported which matches the valid fix 218 // set using SetMockPositionToReturnNext(). 219 GetStatus(); 220 EXPECT_TRUE(status_.has_device_location()); 221 em::DeviceLocation location = status_.device_location(); 222 if (location.has_error_code()) 223 EXPECT_EQ(em::DeviceLocation::ERROR_CODE_NONE, location.error_code()); 224 EXPECT_TRUE(location.has_latitude()); 225 EXPECT_TRUE(location.has_longitude()); 226 EXPECT_TRUE(location.has_accuracy()); 227 EXPECT_TRUE(location.has_timestamp()); 228 EXPECT_FALSE(location.has_altitude()); 229 EXPECT_FALSE(location.has_altitude_accuracy()); 230 EXPECT_FALSE(location.has_heading()); 231 EXPECT_FALSE(location.has_speed()); 232 EXPECT_FALSE(location.has_error_message()); 233 EXPECT_DOUBLE_EQ(4.3, location.latitude()); 234 EXPECT_DOUBLE_EQ(-7.8, location.longitude()); 235 EXPECT_DOUBLE_EQ(3., location.accuracy()); 236 // Check that the timestamp is not older than ten minutes. 237 EXPECT_TRUE(Time::Now() - Time::FromDoubleT(location.timestamp() / 1000.) < 238 TimeDelta::FromMinutes(10)); 239 } 240 241 void CheckThatALocationErrorIsReported() { 242 GetStatus(); 243 EXPECT_TRUE(status_.has_device_location()); 244 em::DeviceLocation location = status_.device_location(); 245 EXPECT_TRUE(location.has_error_code()); 246 EXPECT_EQ(em::DeviceLocation::ERROR_CODE_POSITION_UNAVAILABLE, 247 location.error_code()); 248 } 249 250 protected: 251 // Convenience method. 252 int64 ActivePeriodMilliseconds() { 253 return policy::DeviceStatusCollector::kIdlePollIntervalSeconds * 1000; 254 } 255 256 // Since this is a unit test running in browser_tests we must do additional 257 // unit test setup and make a TestingBrowserProcess. Must be first member. 258 TestingBrowserProcessInitializer initializer_; 259 base::MessageLoopForUI message_loop_; 260 content::TestBrowserThread ui_thread_; 261 content::TestBrowserThread file_thread_; 262 content::TestBrowserThread io_thread_; 263 264 TestingPrefServiceSimple prefs_; 265 chromeos::system::MockStatisticsProvider statistics_provider_; 266 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 267 chromeos::ScopedTestCrosSettings test_cros_settings_; 268 chromeos::CrosSettings* cros_settings_; 269 chromeos::CrosSettingsProvider* device_settings_provider_; 270 chromeos::StubCrosSettingsProvider stub_settings_provider_; 271 chromeos::MockUserManager* user_manager_; 272 chromeos::ScopedUserManagerEnabler user_manager_enabler_; 273 em::DeviceStatusReportRequest status_; 274 scoped_ptr<TestingDeviceStatusCollector> status_collector_; 275}; 276 277TEST_F(DeviceStatusCollectorTest, AllIdle) { 278 IdleState test_states[] = { 279 IDLE_STATE_IDLE, 280 IDLE_STATE_IDLE, 281 IDLE_STATE_IDLE 282 }; 283 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 284 285 // Test reporting with no data. 286 GetStatus(); 287 EXPECT_EQ(0, status_.active_period_size()); 288 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 289 290 // Test reporting with a single idle sample. 291 status_collector_->Simulate(test_states, 1); 292 GetStatus(); 293 EXPECT_EQ(0, status_.active_period_size()); 294 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 295 296 // Test reporting with multiple consecutive idle samples. 297 status_collector_->Simulate(test_states, 298 sizeof(test_states) / sizeof(IdleState)); 299 GetStatus(); 300 EXPECT_EQ(0, status_.active_period_size()); 301 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 302} 303 304TEST_F(DeviceStatusCollectorTest, AllActive) { 305 IdleState test_states[] = { 306 IDLE_STATE_ACTIVE, 307 IDLE_STATE_ACTIVE, 308 IDLE_STATE_ACTIVE 309 }; 310 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 311 312 // Test a single active sample. 313 status_collector_->Simulate(test_states, 1); 314 GetStatus(); 315 EXPECT_EQ(1, status_.active_period_size()); 316 EXPECT_EQ(1 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 317 status_.clear_active_period(); // Clear the result protobuf. 318 319 // Test multiple consecutive active samples. 320 status_collector_->Simulate(test_states, 321 sizeof(test_states) / sizeof(IdleState)); 322 GetStatus(); 323 EXPECT_EQ(1, status_.active_period_size()); 324 EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 325} 326 327TEST_F(DeviceStatusCollectorTest, MixedStates) { 328 IdleState test_states[] = { 329 IDLE_STATE_ACTIVE, 330 IDLE_STATE_IDLE, 331 IDLE_STATE_ACTIVE, 332 IDLE_STATE_ACTIVE, 333 IDLE_STATE_IDLE, 334 IDLE_STATE_IDLE, 335 IDLE_STATE_ACTIVE 336 }; 337 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 338 status_collector_->Simulate(test_states, 339 sizeof(test_states) / sizeof(IdleState)); 340 GetStatus(); 341 EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 342} 343 344TEST_F(DeviceStatusCollectorTest, StateKeptInPref) { 345 IdleState test_states[] = { 346 IDLE_STATE_ACTIVE, 347 IDLE_STATE_IDLE, 348 IDLE_STATE_ACTIVE, 349 IDLE_STATE_ACTIVE, 350 IDLE_STATE_IDLE, 351 IDLE_STATE_IDLE 352 }; 353 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 354 status_collector_->Simulate(test_states, 355 sizeof(test_states) / sizeof(IdleState)); 356 357 // Process the list a second time after restarting the collector. It should be 358 // able to count the active periods found by the original collector, because 359 // the results are stored in a pref. 360 RestartStatusCollector(); 361 status_collector_->Simulate(test_states, 362 sizeof(test_states) / sizeof(IdleState)); 363 364 GetStatus(); 365 EXPECT_EQ(6 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 366} 367 368TEST_F(DeviceStatusCollectorTest, Times) { 369 IdleState test_states[] = { 370 IDLE_STATE_ACTIVE, 371 IDLE_STATE_IDLE, 372 IDLE_STATE_ACTIVE, 373 IDLE_STATE_ACTIVE, 374 IDLE_STATE_IDLE, 375 IDLE_STATE_IDLE 376 }; 377 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 378 status_collector_->Simulate(test_states, 379 sizeof(test_states) / sizeof(IdleState)); 380 GetStatus(); 381 EXPECT_EQ(3 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 382} 383 384TEST_F(DeviceStatusCollectorTest, MaxStoredPeriods) { 385 IdleState test_states[] = { 386 IDLE_STATE_ACTIVE, 387 IDLE_STATE_IDLE 388 }; 389 const int kMaxDays = 10; 390 391 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 392 status_collector_->set_max_stored_past_activity_days(kMaxDays - 1); 393 status_collector_->set_max_stored_future_activity_days(1); 394 Time baseline = Time::Now().LocalMidnight(); 395 396 // Simulate 12 active periods. 397 for (int i = 0; i < kMaxDays + 2; i++) { 398 status_collector_->Simulate(test_states, 399 sizeof(test_states) / sizeof(IdleState)); 400 // Advance the simulated clock by a day. 401 baseline += TimeDelta::FromDays(1); 402 status_collector_->SetBaselineTime(baseline); 403 } 404 405 // Check that we don't exceed the max number of periods. 406 GetStatus(); 407 EXPECT_EQ(kMaxDays - 1, status_.active_period_size()); 408 409 // Simulate some future times. 410 for (int i = 0; i < kMaxDays + 2; i++) { 411 status_collector_->Simulate(test_states, 412 sizeof(test_states) / sizeof(IdleState)); 413 // Advance the simulated clock by a day. 414 baseline += TimeDelta::FromDays(1); 415 status_collector_->SetBaselineTime(baseline); 416 } 417 // Set the clock back so the previous simulated times are in the future. 418 baseline -= TimeDelta::FromDays(20); 419 status_collector_->SetBaselineTime(baseline); 420 421 // Collect one more data point to trigger pruning. 422 status_collector_->Simulate(test_states, 1); 423 424 // Check that we don't exceed the max number of periods. 425 status_.clear_active_period(); 426 GetStatus(); 427 EXPECT_LT(status_.active_period_size(), kMaxDays); 428} 429 430TEST_F(DeviceStatusCollectorTest, ActivityTimesDisabledByDefault) { 431 // If the pref for collecting device activity times isn't explicitly turned 432 // on, no data on activity times should be reported. 433 434 IdleState test_states[] = { 435 IDLE_STATE_ACTIVE, 436 IDLE_STATE_ACTIVE, 437 IDLE_STATE_ACTIVE 438 }; 439 status_collector_->Simulate(test_states, 440 sizeof(test_states) / sizeof(IdleState)); 441 GetStatus(); 442 EXPECT_EQ(0, status_.active_period_size()); 443 EXPECT_EQ(0, GetActiveMilliseconds(status_)); 444} 445 446TEST_F(DeviceStatusCollectorTest, ActivityCrossingMidnight) { 447 IdleState test_states[] = { 448 IDLE_STATE_ACTIVE 449 }; 450 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 451 452 // Set the baseline time to 10 seconds after midnight. 453 status_collector_->SetBaselineTime( 454 Time::Now().LocalMidnight() + TimeDelta::FromSeconds(10)); 455 456 status_collector_->Simulate(test_states, 1); 457 GetStatus(); 458 ASSERT_EQ(2, status_.active_period_size()); 459 460 em::ActiveTimePeriod period0 = status_.active_period(0); 461 em::ActiveTimePeriod period1 = status_.active_period(1); 462 EXPECT_EQ(ActivePeriodMilliseconds() - 10000, period0.active_duration()); 463 EXPECT_EQ(10000, period1.active_duration()); 464 465 em::TimePeriod time_period0 = period0.time_period(); 466 em::TimePeriod time_period1 = period1.time_period(); 467 468 EXPECT_EQ(time_period0.end_timestamp(), time_period1.start_timestamp()); 469 470 // Ensure that the start and end times for the period are a day apart. 471 EXPECT_EQ(time_period0.end_timestamp() - time_period0.start_timestamp(), 472 kMillisecondsPerDay); 473 EXPECT_EQ(time_period1.end_timestamp() - time_period1.start_timestamp(), 474 kMillisecondsPerDay); 475} 476 477TEST_F(DeviceStatusCollectorTest, ActivityTimesKeptUntilSubmittedSuccessfully) { 478 IdleState test_states[] = { 479 IDLE_STATE_ACTIVE, 480 IDLE_STATE_ACTIVE, 481 }; 482 cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); 483 484 status_collector_->Simulate(test_states, 2); 485 GetStatus(); 486 EXPECT_EQ(2 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 487 em::DeviceStatusReportRequest first_status(status_); 488 489 // The collector returns the same status again. 490 GetStatus(); 491 EXPECT_EQ(first_status.SerializeAsString(), status_.SerializeAsString()); 492 493 // After indicating a successful submit, the submitted status gets cleared, 494 // but what got collected meanwhile sticks around. 495 status_collector_->Simulate(test_states, 1); 496 status_collector_->OnSubmittedSuccessfully(); 497 GetStatus(); 498 EXPECT_EQ(ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); 499} 500 501TEST_F(DeviceStatusCollectorTest, DevSwitchBootMode) { 502 // Test that boot mode data is not reported if the pref is not turned on. 503 EXPECT_CALL(statistics_provider_, 504 GetMachineStatistic("devsw_boot", NotNull())) 505 .WillRepeatedly(DoAll(SetArgPointee<1>("0"), Return(true))); 506 GetStatus(); 507 EXPECT_FALSE(status_.has_boot_mode()); 508 509 // Turn the pref on, and check that the status is reported iff the 510 // statistics provider returns valid data. 511 cros_settings_->SetBoolean(chromeos::kReportDeviceBootMode, true); 512 513 EXPECT_CALL(statistics_provider_, 514 GetMachineStatistic("devsw_boot", NotNull())) 515 .WillOnce(DoAll(SetArgPointee<1>("(error)"), Return(true))); 516 GetStatus(); 517 EXPECT_FALSE(status_.has_boot_mode()); 518 519 EXPECT_CALL(statistics_provider_, 520 GetMachineStatistic("devsw_boot", NotNull())) 521 .WillOnce(DoAll(SetArgPointee<1>(" "), Return(true))); 522 GetStatus(); 523 EXPECT_FALSE(status_.has_boot_mode()); 524 525 EXPECT_CALL(statistics_provider_, 526 GetMachineStatistic("devsw_boot", NotNull())) 527 .WillOnce(DoAll(SetArgPointee<1>("0"), Return(true))); 528 GetStatus(); 529 EXPECT_EQ("Verified", status_.boot_mode()); 530 531 EXPECT_CALL(statistics_provider_, 532 GetMachineStatistic("devsw_boot", NotNull())) 533 .WillOnce(DoAll(SetArgPointee<1>("1"), Return(true))); 534 GetStatus(); 535 EXPECT_EQ("Dev", status_.boot_mode()); 536} 537 538TEST_F(DeviceStatusCollectorTest, VersionInfo) { 539 // When the pref to collect this data is not enabled, expect that none of 540 // the fields are present in the protobuf. 541 GetStatus(); 542 EXPECT_FALSE(status_.has_browser_version()); 543 EXPECT_FALSE(status_.has_os_version()); 544 EXPECT_FALSE(status_.has_firmware_version()); 545 546 cros_settings_->SetBoolean(chromeos::kReportDeviceVersionInfo, true); 547 GetStatus(); 548 EXPECT_TRUE(status_.has_browser_version()); 549 EXPECT_TRUE(status_.has_os_version()); 550 EXPECT_TRUE(status_.has_firmware_version()); 551 552 // Check that the browser version is not empty. OS version & firmware 553 // don't have any reasonable values inside the unit test, so those 554 // aren't checked. 555 EXPECT_NE("", status_.browser_version()); 556} 557 558TEST_F(DeviceStatusCollectorTest, Location) { 559 content::Geoposition valid_fix; 560 valid_fix.latitude = 4.3; 561 valid_fix.longitude = -7.8; 562 valid_fix.accuracy = 3.; 563 valid_fix.timestamp = Time::Now(); 564 565 content::Geoposition invalid_fix; 566 invalid_fix.error_code = 567 content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 568 invalid_fix.timestamp = Time::Now(); 569 570 // Check that when device location reporting is disabled, no location is 571 // reported. 572 SetMockPositionToReturnNext(valid_fix); 573 CheckThatNoLocationIsReported(); 574 575 // Check that when device location reporting is enabled and a valid fix is 576 // available, the location is reported and is stored in local state. 577 SetMockPositionToReturnNext(valid_fix); 578 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); 579 EXPECT_FALSE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); 580 CheckThatAValidLocationIsReported(); 581 582 // Restart the status collector. Check that the last known location has been 583 // retrieved from local state without requesting a geolocation update. 584 SetMockPositionToReturnNext(valid_fix); 585 RestartStatusCollector(); 586 CheckThatAValidLocationIsReported(); 587 EXPECT_TRUE(mock_position_to_return_next.get()); 588 589 // Check that after disabling location reporting again, the last known 590 // location has been cleared from local state and is no longer reported. 591 SetMockPositionToReturnNext(valid_fix); 592 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, false); 593 // Allow the new pref to propagate to the status collector. 594 message_loop_.RunUntilIdle(); 595 EXPECT_TRUE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); 596 CheckThatNoLocationIsReported(); 597 598 // Check that after enabling location reporting again, an error is reported 599 // if no valid fix is available. 600 SetMockPositionToReturnNext(invalid_fix); 601 cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); 602 // Allow the new pref to propagate to the status collector. 603 message_loop_.RunUntilIdle(); 604 CheckThatALocationErrorIsReported(); 605} 606 607TEST_F(DeviceStatusCollectorTest, ReportUsers) { 608 user_manager_->CreatePublicAccountUser("public@localhost"); 609 user_manager_->AddUser("user0@managed.com"); 610 user_manager_->AddUser("user1@managed.com"); 611 user_manager_->AddUser("user2@managed.com"); 612 user_manager_->AddUser("user3@unmanaged.com"); 613 user_manager_->AddUser("user4@managed.com"); 614 user_manager_->AddUser("user5@managed.com"); 615 616 // Verify that users are not reported by default. 617 GetStatus(); 618 EXPECT_EQ(0, status_.user_size()); 619 620 // Verify that users are reported after enabling the setting. 621 cros_settings_->SetBoolean(chromeos::kReportDeviceUsers, true); 622 GetStatus(); 623 EXPECT_EQ(5, status_.user_size()); 624 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(0).type()); 625 EXPECT_EQ("user0@managed.com", status_.user(0).email()); 626 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(1).type()); 627 EXPECT_EQ("user1@managed.com", status_.user(1).email()); 628 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(2).type()); 629 EXPECT_EQ("user2@managed.com", status_.user(2).email()); 630 EXPECT_EQ(em::DeviceUser::USER_TYPE_UNMANAGED, status_.user(3).type()); 631 EXPECT_FALSE(status_.user(3).has_email()); 632 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(4).type()); 633 EXPECT_EQ("user4@managed.com", status_.user(4).email()); 634 635 // Verify that users are no longer reported if setting is disabled. 636 cros_settings_->SetBoolean(chromeos::kReportDeviceUsers, false); 637 GetStatus(); 638 EXPECT_EQ(0, status_.user_size()); 639} 640 641TEST_F(DeviceStatusCollectorTest, ReportManagedUser) { 642 // Verify that at least one managed user is reported regardless of list size. 643 user_manager_->AddUser("user0@unmanaged.com"); 644 user_manager_->AddUser("user1@unmanaged.com"); 645 user_manager_->AddUser("user2@unmanaged.com"); 646 user_manager_->AddUser("user3@unmanaged.com"); 647 user_manager_->AddUser("user4@unmanaged.com"); 648 user_manager_->AddUser("user5@unmanaged.com"); 649 user_manager_->AddUser("user6@managed.com"); 650 user_manager_->AddUser("user7@managed.com"); 651 652 cros_settings_->SetBoolean(chromeos::kReportDeviceUsers, true); 653 GetStatus(); 654 EXPECT_EQ(7, status_.user_size()); 655 for (int i = 0; i < 6; ++i) 656 EXPECT_EQ(em::DeviceUser::USER_TYPE_UNMANAGED, status_.user(i).type()); 657 EXPECT_EQ(em::DeviceUser::USER_TYPE_MANAGED, status_.user(6).type()); 658 EXPECT_EQ("user6@managed.com", status_.user(6).email()); 659} 660 661// Fake device state. 662struct FakeDeviceData { 663 const char* device_path; 664 const char* type; 665 const char* object_path; 666 const char* mac_address; 667 const char* meid; 668 const char* imei; 669 int expected_type; // proto enum type value, -1 for not present. 670}; 671 672static const FakeDeviceData kFakeDevices[] = { 673 { "/device/ethernet", shill::kTypeEthernet, "ethernet", 674 "112233445566", "", "", 675 em::NetworkInterface::TYPE_ETHERNET }, 676 { "/device/cellular1", shill::kTypeCellular, "cellular1", 677 "abcdefabcdef", "A10000009296F2", "", 678 em::NetworkInterface::TYPE_CELLULAR }, 679 { "/device/cellular2", shill::kTypeCellular, "cellular2", 680 "abcdefabcdef", "", "352099001761481", 681 em::NetworkInterface::TYPE_CELLULAR }, 682 { "/device/wifi", shill::kTypeWifi, "wifi", 683 "aabbccddeeff", "", "", 684 em::NetworkInterface::TYPE_WIFI }, 685 { "/device/bluetooth", shill::kTypeBluetooth, "bluetooth", 686 "", "", "", 687 em::NetworkInterface::TYPE_BLUETOOTH }, 688 { "/device/vpn", shill::kTypeVPN, "vpn", 689 "", "", "", 690 -1 }, 691}; 692 693class DeviceStatusCollectorNetworkInterfacesTest 694 : public DeviceStatusCollectorTest { 695 protected: 696 virtual void SetUp() OVERRIDE { 697 chromeos::DBusThreadManager::InitializeWithStub(); 698 chromeos::NetworkHandler::Initialize(); 699 chromeos::ShillDeviceClient::TestInterface* test_device_client = 700 chromeos::DBusThreadManager::Get()->GetShillDeviceClient()-> 701 GetTestInterface(); 702 test_device_client->ClearDevices(); 703 for (size_t i = 0; i < arraysize(kFakeDevices); ++i) { 704 const FakeDeviceData& dev = kFakeDevices[i]; 705 test_device_client->AddDevice(dev.device_path, dev.type, 706 dev.object_path); 707 if (*dev.mac_address) { 708 test_device_client->SetDeviceProperty( 709 dev.device_path, shill::kAddressProperty, 710 base::StringValue(dev.mac_address)); 711 } 712 if (*dev.meid) { 713 test_device_client->SetDeviceProperty( 714 dev.device_path, shill::kMeidProperty, 715 base::StringValue(dev.meid)); 716 } 717 if (*dev.imei) { 718 test_device_client->SetDeviceProperty( 719 dev.device_path, shill::kImeiProperty, 720 base::StringValue(dev.imei)); 721 } 722 } 723 724 // Flush out pending state updates. 725 base::RunLoop().RunUntilIdle(); 726 } 727 728 virtual void TearDown() OVERRIDE { 729 chromeos::NetworkHandler::Shutdown(); 730 chromeos::DBusThreadManager::Shutdown(); 731 } 732}; 733 734TEST_F(DeviceStatusCollectorNetworkInterfacesTest, NetworkInterfaces) { 735 // No interfaces should be reported if the policy is off. 736 GetStatus(); 737 EXPECT_EQ(0, status_.network_interface_size()); 738 739 // Switch the policy on and verify the interface list is present. 740 cros_settings_->SetBoolean(chromeos::kReportDeviceNetworkInterfaces, true); 741 GetStatus(); 742 743 int count = 0; 744 for (size_t i = 0; i < arraysize(kFakeDevices); ++i) { 745 const FakeDeviceData& dev = kFakeDevices[i]; 746 if (dev.expected_type == -1) 747 continue; 748 749 // Find the corresponding entry in reporting data. 750 bool found_match = false; 751 google::protobuf::RepeatedPtrField<em::NetworkInterface>::const_iterator 752 iface; 753 for (iface = status_.network_interface().begin(); 754 iface != status_.network_interface().end(); 755 ++iface) { 756 // Check whether type, field presence and field values match. 757 if (dev.expected_type == iface->type() && 758 iface->has_mac_address() == !!*dev.mac_address && 759 iface->has_meid() == !!*dev.meid && 760 iface->has_imei() == !!*dev.imei && 761 iface->mac_address() == dev.mac_address && 762 iface->meid() == dev.meid && 763 iface->imei() == dev.imei) { 764 found_match = true; 765 break; 766 } 767 } 768 769 EXPECT_TRUE(found_match) << "No matching interface for fake device " << i; 770 count++; 771 } 772 773 EXPECT_EQ(count, status_.network_interface_size()); 774} 775 776} // namespace policy 777