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