diff options
Diffstat (limited to 'chrome/browser/policy/device_status_collector_unittest.cc')
-rw-r--r-- | chrome/browser/policy/device_status_collector_unittest.cc | 287 |
1 files changed, 204 insertions, 83 deletions
diff --git a/chrome/browser/policy/device_status_collector_unittest.cc b/chrome/browser/policy/device_status_collector_unittest.cc index 3dcfb3f..ca4ff99 100644 --- a/chrome/browser/policy/device_status_collector_unittest.cc +++ b/chrome/browser/policy/device_status_collector_unittest.cc @@ -4,21 +4,29 @@ #include "chrome/browser/policy/device_status_collector.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/message_loop.h" -#include "base/time.h" -#include "chrome/browser/idle.h" #include "chrome/browser/chromeos/cros_settings.h" #include "chrome/browser/chromeos/cros_settings_names.h" #include "chrome/browser/chromeos/cros_settings_provider.h" #include "chrome/browser/chromeos/stub_cros_settings_provider.h" #include "chrome/browser/chromeos/system/mock_statistics_provider.h" +#include "chrome/browser/chromeos/system/statistics_provider.h" #include "chrome/browser/policy/proto/device_management_backend.pb.h" #include "chrome/browser/prefs/pref_service.h" +#include "chrome/common/pref_names.h" #include "chrome/test/base/testing_pref_service.h" +#include "content/public/browser/browser_thread.h" #include "content/test/test_browser_thread.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using ::testing::_; +using ::testing::DoAll; +using ::testing::NotNull; +using ::testing::Return; +using ::testing::SetArgPointee; using base::TimeDelta; using base::Time; @@ -28,13 +36,36 @@ namespace { const int64 kMillisecondsPerDay = Time::kMicrosecondsPerDay / 1000; +scoped_ptr<content::Geoposition> mock_position_to_return_next; + +void SetMockPositionToReturnNext(const content::Geoposition &position) { + mock_position_to_return_next.reset(new content::Geoposition(position)); +} + +void MockPositionUpdateRequester( + const content::GeolocationUpdateCallback& callback) { + if (!mock_position_to_return_next.get()) + return; + + // If the fix is invalid, the DeviceStatusCollector will immediately request + // another update when it receives the callback. This is desirable and safe in + // real life where geolocation updates arrive asynchronously. In this testing + // harness, the callback is invoked synchronously upon request, leading to a + // request-callback loop. The loop is broken by returning the mock position + // only once. + scoped_ptr<content::Geoposition> position( + mock_position_to_return_next.release()); + callback.Run(*position); +} + class TestingDeviceStatusCollector : public policy::DeviceStatusCollector { public: TestingDeviceStatusCollector( PrefService* local_state, chromeos::system::StatisticsProvider* provider) - : policy::DeviceStatusCollector(local_state, provider), - local_state_(local_state) { + : policy::DeviceStatusCollector(local_state, + provider, + &MockPositionUpdateRequester) { // Set the baseline time to a fixed value (1 AM) to prevent test flakiness // due to a single activity period spanning two days. SetBaselineTime(Time::Now().LocalMidnight() + TimeDelta::FromHours(1)); @@ -68,14 +99,12 @@ class TestingDeviceStatusCollector : public policy::DeviceStatusCollector { // Each time this is called, returns a time that is a fixed increment // later than the previous time. virtual Time GetCurrentTime() OVERRIDE { - int poll_interval = policy::DeviceStatusCollector::kPollIntervalSeconds; + int poll_interval = policy::DeviceStatusCollector::kIdlePollIntervalSeconds; return baseline_time_ + TimeDelta::FromSeconds(poll_interval * baseline_offset_periods_++); } private: - PrefService* local_state_; - // Baseline time for the fake times returned from GetCurrentTime(). Time baseline_time_; @@ -97,32 +126,28 @@ int64 GetActiveMilliseconds(em::DeviceStatusReportRequest& status) { namespace policy { -using ::testing::_; -using ::testing::NotNull; -using ::testing::Return; -using ::testing::SetArgPointee; - class DeviceStatusCollectorTest : public testing::Test { public: DeviceStatusCollectorTest() : message_loop_(MessageLoop::TYPE_UI), ui_thread_(content::BrowserThread::UI, &message_loop_), file_thread_(content::BrowserThread::FILE, &message_loop_), - status_collector_(&prefs_, &statistics_provider_) { + io_thread_(content::BrowserThread::IO, &message_loop_) { + TestingDeviceStatusCollector::RegisterPrefs(&prefs_); - DeviceStatusCollector::RegisterPrefs(&prefs_); EXPECT_CALL(statistics_provider_, GetMachineStatistic(_, NotNull())) .WillRepeatedly(Return(false)); - cros_settings_ = chromeos::CrosSettings::Get(); - // Remove the real DeviceSettingsProvider and replace it with a stub. + cros_settings_ = chromeos::CrosSettings::Get(); device_settings_provider_ = cros_settings_->GetProvider(chromeos::kReportDeviceVersionInfo); EXPECT_TRUE(device_settings_provider_ != NULL); EXPECT_TRUE( cros_settings_->RemoveSettingsProvider(device_settings_provider_)); cros_settings_->AddSettingsProvider(&stub_settings_provider_); + + RestartStatusCollector(); } ~DeviceStatusCollectorTest() { @@ -132,19 +157,69 @@ class DeviceStatusCollectorTest : public testing::Test { cros_settings_->AddSettingsProvider(device_settings_provider_); } + void RestartStatusCollector() { + status_collector_.reset( + new TestingDeviceStatusCollector(&prefs_, &statistics_provider_)); + } + + void GetStatus() { + status_.Clear(); + status_collector_->GetStatus(&status_); + } + + void CheckThatNoLocationIsReported() { + GetStatus(); + EXPECT_FALSE(status_.has_device_location()); + } + + void CheckThatAValidLocationIsReported() { + // Checks that a location is being reported which matches the valid fix + // set using SetMockPositionToReturnNext(). + GetStatus(); + EXPECT_TRUE(status_.has_device_location()); + em::DeviceLocation location = status_.device_location(); + if (location.has_error_code()) + EXPECT_EQ(em::DeviceLocation::ERROR_CODE_NONE, location.error_code()); + EXPECT_TRUE(location.has_latitude()); + EXPECT_TRUE(location.has_longitude()); + EXPECT_TRUE(location.has_accuracy()); + EXPECT_TRUE(location.has_timestamp()); + EXPECT_FALSE(location.has_altitude()); + EXPECT_FALSE(location.has_altitude_accuracy()); + EXPECT_FALSE(location.has_heading()); + EXPECT_FALSE(location.has_speed()); + EXPECT_FALSE(location.has_error_message()); + EXPECT_DOUBLE_EQ(4.3, location.latitude()); + EXPECT_DOUBLE_EQ(-7.8, location.longitude()); + EXPECT_DOUBLE_EQ(3., location.accuracy()); + // Check that the timestamp is not older than ten minutes. + EXPECT_TRUE(Time::Now() - Time::FromDoubleT(location.timestamp() / 1000.) < + TimeDelta::FromMinutes(10)); + } + + void CheckThatALocationErrorIsReported() { + GetStatus(); + EXPECT_TRUE(status_.has_device_location()); + em::DeviceLocation location = status_.device_location(); + EXPECT_TRUE(location.has_error_code()); + EXPECT_EQ(em::DeviceLocation::ERROR_CODE_POSITION_UNAVAILABLE, + location.error_code()); + } + protected: // Convenience method. int64 ActivePeriodMilliseconds() { - return policy::DeviceStatusCollector::kPollIntervalSeconds * 1000; + return policy::DeviceStatusCollector::kIdlePollIntervalSeconds * 1000; } MessageLoop message_loop_; content::TestBrowserThread ui_thread_; content::TestBrowserThread file_thread_; + content::TestBrowserThread io_thread_; TestingPrefService prefs_; chromeos::system::MockStatisticsProvider statistics_provider_; - TestingDeviceStatusCollector status_collector_; + scoped_ptr<TestingDeviceStatusCollector> status_collector_; em::DeviceStatusReportRequest status_; chromeos::CrosSettings* cros_settings_; chromeos::CrosSettingsProvider* device_settings_provider_; @@ -160,20 +235,20 @@ TEST_F(DeviceStatusCollectorTest, AllIdle) { cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); // Test reporting with no data. - status_collector_.GetStatus(&status_); + GetStatus(); EXPECT_EQ(0, status_.active_period_size()); EXPECT_EQ(0, GetActiveMilliseconds(status_)); // Test reporting with a single idle sample. - status_collector_.Simulate(test_states, 1); - status_collector_.GetStatus(&status_); + status_collector_->Simulate(test_states, 1); + GetStatus(); EXPECT_EQ(0, status_.active_period_size()); EXPECT_EQ(0, GetActiveMilliseconds(status_)); // Test reporting with multiple consecutive idle samples. - status_collector_.Simulate(test_states, - sizeof(test_states) / sizeof(IdleState)); - status_collector_.GetStatus(&status_); + status_collector_->Simulate(test_states, + sizeof(test_states) / sizeof(IdleState)); + GetStatus(); EXPECT_EQ(0, status_.active_period_size()); EXPECT_EQ(0, GetActiveMilliseconds(status_)); } @@ -187,16 +262,16 @@ TEST_F(DeviceStatusCollectorTest, AllActive) { cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); // Test a single active sample. - status_collector_.Simulate(test_states, 1); - status_collector_.GetStatus(&status_); + status_collector_->Simulate(test_states, 1); + GetStatus(); EXPECT_EQ(1, status_.active_period_size()); EXPECT_EQ(1 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); status_.clear_active_period(); // Clear the result protobuf. // Test multiple consecutive active samples. - status_collector_.Simulate(test_states, - sizeof(test_states) / sizeof(IdleState)); - status_collector_.GetStatus(&status_); + status_collector_->Simulate(test_states, + sizeof(test_states) / sizeof(IdleState)); + GetStatus(); EXPECT_EQ(1, status_.active_period_size()); EXPECT_EQ(3 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); } @@ -212,9 +287,9 @@ TEST_F(DeviceStatusCollectorTest, MixedStates) { IDLE_STATE_ACTIVE }; cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); - status_collector_.Simulate(test_states, - sizeof(test_states) / sizeof(IdleState)); - status_collector_.GetStatus(&status_); + status_collector_->Simulate(test_states, + sizeof(test_states) / sizeof(IdleState)); + GetStatus(); EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); } @@ -228,18 +303,17 @@ TEST_F(DeviceStatusCollectorTest, StateKeptInPref) { IDLE_STATE_IDLE }; cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); - status_collector_.Simulate(test_states, - sizeof(test_states) / sizeof(IdleState)); - - // Process the list a second time with a different collector. - // It should be able to count the active periods found by the first - // collector, because the results are stored in a pref. - TestingDeviceStatusCollector second_collector(&prefs_, - &statistics_provider_); - second_collector.Simulate(test_states, - sizeof(test_states) / sizeof(IdleState)); - - second_collector.GetStatus(&status_); + status_collector_->Simulate(test_states, + sizeof(test_states) / sizeof(IdleState)); + + // Process the list a second time after restarting the collector. It should be + // able to count the active periods found by the original collector, because + // the results are stored in a pref. + RestartStatusCollector(); + status_collector_->Simulate(test_states, + sizeof(test_states) / sizeof(IdleState)); + + GetStatus(); EXPECT_EQ(6 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); } @@ -253,9 +327,9 @@ TEST_F(DeviceStatusCollectorTest, Times) { IDLE_STATE_IDLE }; cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); - status_collector_.Simulate(test_states, - sizeof(test_states) / sizeof(IdleState)); - status_collector_.GetStatus(&status_); + status_collector_->Simulate(test_states, + sizeof(test_states) / sizeof(IdleState)); + GetStatus(); EXPECT_EQ(3 * ActivePeriodMilliseconds(), GetActiveMilliseconds(status_)); } @@ -267,41 +341,41 @@ TEST_F(DeviceStatusCollectorTest, MaxStoredPeriods) { unsigned int max_days = 10; cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); - status_collector_.set_max_stored_past_activity_days(max_days - 1); - status_collector_.set_max_stored_future_activity_days(1); + status_collector_->set_max_stored_past_activity_days(max_days - 1); + status_collector_->set_max_stored_future_activity_days(1); Time baseline = Time::Now().LocalMidnight(); // Simulate 12 active periods. for (int i = 0; i < static_cast<int>(max_days) + 2; i++) { - status_collector_.Simulate(test_states, - sizeof(test_states) / sizeof(IdleState)); + status_collector_->Simulate(test_states, + sizeof(test_states) / sizeof(IdleState)); // Advance the simulated clock by a day. baseline += TimeDelta::FromDays(1); - status_collector_.SetBaselineTime(baseline); + status_collector_->SetBaselineTime(baseline); } // Check that we don't exceed the max number of periods. - status_collector_.GetStatus(&status_); + GetStatus(); EXPECT_EQ(static_cast<int>(max_days), status_.active_period_size()); // Simulate some future times. for (int i = 0; i < static_cast<int>(max_days) + 2; i++) { - status_collector_.Simulate(test_states, - sizeof(test_states) / sizeof(IdleState)); + status_collector_->Simulate(test_states, + sizeof(test_states) / sizeof(IdleState)); // Advance the simulated clock by a day. baseline += TimeDelta::FromDays(1); - status_collector_.SetBaselineTime(baseline); + status_collector_->SetBaselineTime(baseline); } // Set the clock back so the previous simulated times are in the future. baseline -= TimeDelta::FromDays(20); - status_collector_.SetBaselineTime(baseline); + status_collector_->SetBaselineTime(baseline); // Collect one more data point to trigger pruning. - status_collector_.Simulate(test_states, 1); + status_collector_->Simulate(test_states, 1); // Check that we don't exceed the max number of periods. status_.clear_active_period(); - status_collector_.GetStatus(&status_); + GetStatus(); EXPECT_LT(status_.active_period_size(), static_cast<int>(max_days)); } @@ -314,9 +388,9 @@ TEST_F(DeviceStatusCollectorTest, ActivityTimesDisabledByDefault) { IDLE_STATE_ACTIVE, IDLE_STATE_ACTIVE }; - status_collector_.Simulate(test_states, - sizeof(test_states) / sizeof(IdleState)); - status_collector_.GetStatus(&status_); + status_collector_->Simulate(test_states, + sizeof(test_states) / sizeof(IdleState)); + GetStatus(); EXPECT_EQ(0, status_.active_period_size()); EXPECT_EQ(0, GetActiveMilliseconds(status_)); } @@ -328,11 +402,11 @@ TEST_F(DeviceStatusCollectorTest, ActivityCrossingMidnight) { cros_settings_->SetBoolean(chromeos::kReportDeviceActivityTimes, true); // Set the baseline time to 10 seconds after midnight. - status_collector_.SetBaselineTime( + status_collector_->SetBaselineTime( Time::Now().LocalMidnight() + TimeDelta::FromSeconds(10)); - status_collector_.Simulate(test_states, 1); - status_collector_.GetStatus(&status_); + status_collector_->Simulate(test_states, 1); + GetStatus(); ASSERT_EQ(2, status_.active_period_size()); em::ActiveTimePeriod period0 = status_.active_period(0); @@ -354,13 +428,11 @@ TEST_F(DeviceStatusCollectorTest, ActivityCrossingMidnight) { TEST_F(DeviceStatusCollectorTest, DevSwitchBootMode) { // Test that boot mode data is not reported if the pref is not turned on. - status_collector_.GetStatus(&status_); - EXPECT_EQ(false, status_.has_boot_mode()); - EXPECT_CALL(statistics_provider_, GetMachineStatistic("devsw_boot", NotNull())) .WillRepeatedly(DoAll(SetArgPointee<1>("0"), Return(true))); - EXPECT_EQ(false, status_.has_boot_mode()); + GetStatus(); + EXPECT_FALSE(status_.has_boot_mode()); // Turn the pref on, and check that the status is reported iff the // statistics provider returns valid data. @@ -369,41 +441,41 @@ TEST_F(DeviceStatusCollectorTest, DevSwitchBootMode) { EXPECT_CALL(statistics_provider_, GetMachineStatistic("devsw_boot", NotNull())) .WillOnce(DoAll(SetArgPointee<1>("(error)"), Return(true))); - status_collector_.GetStatus(&status_); - EXPECT_EQ(false, status_.has_boot_mode()); + GetStatus(); + EXPECT_FALSE(status_.has_boot_mode()); EXPECT_CALL(statistics_provider_, GetMachineStatistic("devsw_boot", NotNull())) .WillOnce(DoAll(SetArgPointee<1>(" "), Return(true))); - status_collector_.GetStatus(&status_); - EXPECT_EQ(false, status_.has_boot_mode()); + GetStatus(); + EXPECT_FALSE(status_.has_boot_mode()); EXPECT_CALL(statistics_provider_, GetMachineStatistic("devsw_boot", NotNull())) .WillOnce(DoAll(SetArgPointee<1>("0"), Return(true))); - status_collector_.GetStatus(&status_); + GetStatus(); EXPECT_EQ("Verified", status_.boot_mode()); EXPECT_CALL(statistics_provider_, GetMachineStatistic("devsw_boot", NotNull())) .WillOnce(DoAll(SetArgPointee<1>("1"), Return(true))); - status_collector_.GetStatus(&status_); + GetStatus(); EXPECT_EQ("Dev", status_.boot_mode()); } TEST_F(DeviceStatusCollectorTest, VersionInfo) { // When the pref to collect this data is not enabled, expect that none of // the fields are present in the protobuf. - status_collector_.GetStatus(&status_); - EXPECT_EQ(false, status_.has_browser_version()); - EXPECT_EQ(false, status_.has_os_version()); - EXPECT_EQ(false, status_.has_firmware_version()); + GetStatus(); + EXPECT_FALSE(status_.has_browser_version()); + EXPECT_FALSE(status_.has_os_version()); + EXPECT_FALSE(status_.has_firmware_version()); cros_settings_->SetBoolean(chromeos::kReportDeviceVersionInfo, true); - status_collector_.GetStatus(&status_); - EXPECT_EQ(true, status_.has_browser_version()); - EXPECT_EQ(true, status_.has_os_version()); - EXPECT_EQ(true, status_.has_firmware_version()); + GetStatus(); + EXPECT_TRUE(status_.has_browser_version()); + EXPECT_TRUE(status_.has_os_version()); + EXPECT_TRUE(status_.has_firmware_version()); // Check that the browser version is not empty. OS version & firmware // don't have any reasonable values inside the unit test, so those @@ -411,4 +483,53 @@ TEST_F(DeviceStatusCollectorTest, VersionInfo) { EXPECT_NE("", status_.browser_version()); } +TEST_F(DeviceStatusCollectorTest, Location) { + content::Geoposition valid_fix; + valid_fix.latitude = 4.3; + valid_fix.longitude = -7.8; + valid_fix.accuracy = 3.; + valid_fix.timestamp = Time::Now(); + + content::Geoposition invalid_fix; + invalid_fix.error_code = + content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; + invalid_fix.timestamp = Time::Now(); + + // Check that when device location reporting is disabled, no location is + // reported. + SetMockPositionToReturnNext(valid_fix); + CheckThatNoLocationIsReported(); + + // Check that when device location reporting is enabled and a valid fix is + // available, the location is reported and is stored in local state. + SetMockPositionToReturnNext(valid_fix); + cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); + EXPECT_FALSE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); + CheckThatAValidLocationIsReported(); + + // Restart the status collector. Check that the last known location has been + // retrieved from local state without requesting a geolocation update. + SetMockPositionToReturnNext(valid_fix); + RestartStatusCollector(); + CheckThatAValidLocationIsReported(); + EXPECT_TRUE(mock_position_to_return_next.get()); + + // Check that after disabling location reporting again, the last known + // location has been cleared from local state and is no longer reported. + SetMockPositionToReturnNext(valid_fix); + cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, false); + // Allow the new pref to propagate to the status collector. + message_loop_.RunAllPending(); + EXPECT_TRUE(prefs_.GetDictionary(prefs::kDeviceLocation)->empty()); + CheckThatNoLocationIsReported(); + + // Check that after enabling location reporting again, an error is reported + // if no valid fix is available. + SetMockPositionToReturnNext(invalid_fix); + cros_settings_->SetBoolean(chromeos::kReportDeviceLocation, true); + // Allow the new pref to propagate to the status collector. + message_loop_.RunAllPending(); + CheckThatALocationErrorIsReported(); +} + } // namespace policy |