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