1//
2// Copyright (C) 2013 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "shill/service.h"
18
19#include <algorithm>
20#include <map>
21#include <memory>
22#include <string>
23#include <vector>
24
25#include <base/bind.h>
26#if defined(__ANDROID__)
27#include <dbus/service_constants.h>
28#else
29#include <chromeos/dbus/service_constants.h>
30#endif  // __ANDROID__
31#include <gtest/gtest.h>
32#include <gmock/gmock.h>
33
34#include "shill/ethernet/ethernet_service.h"
35#include "shill/event_dispatcher.h"
36#include "shill/manager.h"
37#include "shill/mock_adaptors.h"
38#include "shill/mock_connection.h"
39#include "shill/mock_control.h"
40#include "shill/mock_device_info.h"
41#include "shill/mock_dhcp_properties.h"
42#include "shill/mock_event_dispatcher.h"
43#include "shill/mock_log.h"
44#include "shill/mock_manager.h"
45#include "shill/mock_power_manager.h"
46#include "shill/mock_profile.h"
47#include "shill/mock_service.h"
48#include "shill/mock_store.h"
49#include "shill/net/mock_time.h"
50#include "shill/property_store_unittest.h"
51#include "shill/service_property_change_test.h"
52#include "shill/service_sorter.h"
53#include "shill/service_under_test.h"
54#include "shill/testing.h"
55
56#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
57#include "shill/mock_eap_credentials.h"
58#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
59
60using base::Bind;
61using base::Unretained;
62using std::deque;
63using std::map;
64using std::string;
65using std::vector;
66using testing::_;
67using testing::AnyNumber;
68using testing::AtLeast;
69using testing::DefaultValue;
70using testing::DoAll;
71using testing::HasSubstr;
72using testing::Mock;
73using testing::NiceMock;
74using testing::Return;
75using testing::ReturnNull;
76using testing::ReturnRef;
77using testing::StrictMock;
78using testing::SetArgumentPointee;
79using testing::Test;
80using testing::Values;
81
82namespace shill {
83
84class ServiceTest : public PropertyStoreTest {
85 public:
86  ServiceTest()
87      : mock_manager_(control_interface(), dispatcher(), metrics()),
88        service_(new ServiceUnderTest(control_interface(),
89                                      dispatcher(),
90                                      metrics(),
91                                      &mock_manager_)),
92        service2_(new ServiceUnderTest(control_interface(),
93                                       dispatcher(),
94                                       metrics(),
95                                       &mock_manager_)),
96        storage_id_(ServiceUnderTest::kStorageId),
97#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
98        eap_(new MockEapCredentials()),
99#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
100        power_manager_(new MockPowerManager(nullptr, &control_)) {
101    ON_CALL(control_, CreatePowerManagerProxy(_, _, _))
102        .WillByDefault(ReturnNull());
103
104    service_->time_ = &time_;
105    service_->disconnects_.time_ = &time_;
106    service_->misconnects_.time_ = &time_;
107    DefaultValue<Timestamp>::Set(Timestamp());
108#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
109    service_->eap_.reset(eap_);  // Passes ownership.
110#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
111    mock_manager_.running_ = true;
112    mock_manager_.set_power_manager(power_manager_);  // Passes ownership.
113  }
114
115  virtual ~ServiceTest() {}
116
117  MOCK_METHOD1(TestCallback, void(const Error& error));
118
119 protected:
120  typedef scoped_refptr<MockProfile> MockProfileRefPtr;
121
122  ServiceMockAdaptor* GetAdaptor() {
123    return static_cast<ServiceMockAdaptor*>(service_->adaptor());
124  }
125
126  string GetFriendlyName() { return service_->friendly_name(); }
127
128  void SetManagerRunning(bool running) { mock_manager_.running_ = running; }
129
130  void SetSuspending(bool suspending) {
131    power_manager_->suspending_ = suspending;
132  }
133
134  bool GetExplicitlyDisconnected() const {
135    return service_->explicitly_disconnected_;
136  }
137
138  void SetExplicitlyDisconnected(bool explicitly) {
139    service_->explicitly_disconnected_ = explicitly;
140  }
141
142  void SetStateField(Service::ConnectState state) { service_->state_ = state; }
143
144  Service::ConnectState GetPreviousState() const {
145    return service_->previous_state_;
146  }
147
148  void NoteDisconnectEvent() {
149    service_->NoteDisconnectEvent();
150  }
151
152  EventHistory* GetDisconnects() {
153    return &service_->disconnects_;
154  }
155  EventHistory* GetMisconnects() {
156    return &service_->misconnects_;
157  }
158
159  Timestamp GetTimestamp(int monotonic_seconds, int boottime_seconds,
160                         const string& wall_clock) {
161    struct timeval monotonic = { .tv_sec = monotonic_seconds, .tv_usec = 0 };
162    struct timeval boottime = { .tv_sec = boottime_seconds, .tv_usec = 0 };
163    return Timestamp(monotonic, boottime, wall_clock);
164  }
165
166  void PushTimestamp(EventHistory* events,
167                     int monotonic_seconds,
168                     int boottime_seconds,
169                     const string& wall_clock) {
170    events->RecordEventInternal(
171        GetTimestamp(monotonic_seconds, boottime_seconds, wall_clock));
172  }
173
174  int GetDisconnectsMonitorSeconds() {
175    return Service::kDisconnectsMonitorSeconds;
176  }
177
178  int GetMisconnectsMonitorSeconds() {
179    return Service::kMisconnectsMonitorSeconds;
180  }
181
182  int GetMaxDisconnectEventHistory() {
183    return Service::kMaxDisconnectEventHistory;
184  }
185
186  int GetMaxMisconnectEventHistory() {
187    return Service::kMaxMisconnectEventHistory;
188  }
189
190  bool GetAutoConnect(Error* error) {
191    return service_->GetAutoConnect(error);
192  }
193
194  void ClearAutoConnect(Error* error) {
195    service_->ClearAutoConnect(error);
196  }
197
198  bool SetAutoConnectFull(bool connect, Error* error) {
199    return service_->SetAutoConnectFull(connect, error);
200  }
201
202  bool SortingOrderIs(const ServiceRefPtr& service0,
203                      const ServiceRefPtr& service1,
204                      bool should_compare_connectivity_state) {
205    vector<ServiceRefPtr> services;
206    services.push_back(service1);
207    services.push_back(service0);
208    std::sort(services.begin(), services.end(),
209              ServiceSorter(&mock_manager_, should_compare_connectivity_state,
210                            technology_order_for_sorting_));
211    return (service0.get() == services[0].get() &&
212            service1.get() == services[1].get());
213  }
214
215  bool DefaultSortingOrderIs(const ServiceRefPtr& service0,
216                             const ServiceRefPtr& service1) {
217    const bool kShouldCompareConnectivityState = true;
218    return SortingOrderIs(
219        service0, service1, kShouldCompareConnectivityState);
220  }
221
222  MockManager mock_manager_;
223  MockTime time_;
224  scoped_refptr<ServiceUnderTest> service_;
225  scoped_refptr<ServiceUnderTest> service2_;
226  string storage_id_;
227  NiceMock<MockControl> control_;
228#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
229  MockEapCredentials* eap_;  // Owned by |service_|.
230#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
231  MockPowerManager* power_manager_;  // Owned by |mock_manager_|.
232  vector<Technology::Identifier> technology_order_for_sorting_;
233};
234
235class AllMockServiceTest : public testing::Test {
236 public:
237  AllMockServiceTest()
238      : metrics_(&dispatcher_),
239        manager_(&control_interface_, &dispatcher_, &metrics_),
240        service_(new ServiceUnderTest(&control_interface_,
241                                      &dispatcher_,
242                                      &metrics_,
243                                      &manager_)) { }
244  virtual ~AllMockServiceTest() {}
245
246 protected:
247  MockControl control_interface_;
248  StrictMock<MockEventDispatcher> dispatcher_;
249  NiceMock<MockMetrics> metrics_;
250  MockManager manager_;
251  scoped_refptr<ServiceUnderTest> service_;
252};
253
254TEST_F(ServiceTest, Constructor) {
255  EXPECT_TRUE(service_->save_credentials_);
256  EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
257  EXPECT_EQ(Service::kStateIdle, service_->state());
258  EXPECT_FALSE(service_->has_ever_connected());
259  EXPECT_EQ(0, service_->previous_error_serial_number_);
260  EXPECT_EQ("", service_->previous_error_);
261}
262
263TEST_F(ServiceTest, CalculateState) {
264  service_->state_ = Service::kStateConnected;
265  Error error;
266  EXPECT_EQ(kStateReady, service_->CalculateState(&error));
267  EXPECT_TRUE(error.IsSuccess());
268}
269
270TEST_F(ServiceTest, CalculateTechnology) {
271  service_->technology_ = Technology::kWifi;
272  Error error;
273  EXPECT_EQ(kTypeWifi, service_->CalculateTechnology(&error));
274  EXPECT_TRUE(error.IsSuccess());
275}
276
277TEST_F(ServiceTest, GetProperties) {
278  {
279    brillo::VariantDictionary props;
280    Error error;
281    string expected("true");
282    service_->mutable_store()->SetStringProperty(kCheckPortalProperty,
283                                                 expected,
284                                                 &error);
285    EXPECT_TRUE(service_->store().GetProperties(&props, &error));
286    ASSERT_FALSE(props.find(kCheckPortalProperty) == props.end());
287    EXPECT_TRUE(props[kCheckPortalProperty].IsTypeCompatible<string>());
288    EXPECT_EQ(props[kCheckPortalProperty].Get<string>(), expected);
289  }
290  {
291    brillo::VariantDictionary props;
292    Error error;
293    bool expected = true;
294    service_->mutable_store()->SetBoolProperty(kAutoConnectProperty,
295                                               expected,
296                                               &error);
297    EXPECT_TRUE(service_->store().GetProperties(&props, &error));
298    ASSERT_FALSE(props.find(kAutoConnectProperty) == props.end());
299    EXPECT_TRUE(props[kAutoConnectProperty].IsTypeCompatible<bool>());
300    EXPECT_EQ(props[kAutoConnectProperty].Get<bool>(), expected);
301  }
302  {
303    brillo::VariantDictionary props;
304    Error error;
305    EXPECT_TRUE(service_->store().GetProperties(&props, &error));
306    ASSERT_FALSE(props.find(kConnectableProperty) == props.end());
307    EXPECT_TRUE(props[kConnectableProperty].IsTypeCompatible<bool>());
308    EXPECT_EQ(props[kConnectableProperty].Get<bool>(), false);
309  }
310  {
311    brillo::VariantDictionary props;
312    Error error;
313    int32_t expected = 127;
314    service_->mutable_store()->SetInt32Property(kPriorityProperty,
315                                                expected,
316                                                &error);
317    EXPECT_TRUE(service_->store().GetProperties(&props, &error));
318    ASSERT_FALSE(props.find(kPriorityProperty) == props.end());
319    EXPECT_TRUE(props[kPriorityProperty].IsTypeCompatible<int32_t>());
320    EXPECT_EQ(props[kPriorityProperty].Get<int32_t>(), expected);
321  }
322  {
323    brillo::VariantDictionary props;
324    Error error;
325    service_->store().GetProperties(&props, &error);
326    ASSERT_FALSE(props.find(kDeviceProperty) == props.end());
327    EXPECT_TRUE(props[kDeviceProperty].IsTypeCompatible<dbus::ObjectPath>());
328    EXPECT_EQ(props[kDeviceProperty].Get<dbus::ObjectPath>().value(),
329              string(ServiceUnderTest::kRpcId));
330  }
331}
332
333TEST_F(ServiceTest, SetProperty) {
334  {
335    Error error;
336    EXPECT_TRUE(service_->mutable_store()->SetAnyProperty(
337        kSaveCredentialsProperty, PropertyStoreTest::kBoolV, &error));
338  }
339  {
340    Error error;
341    const int32_t priority = 1;
342    EXPECT_TRUE(service_->mutable_store()->SetAnyProperty(
343        kPriorityProperty, brillo::Any(priority), &error));
344  }
345  {
346    Error error;
347    const string guid("not default");
348    EXPECT_TRUE(service_->mutable_store()->SetAnyProperty(
349        kGuidProperty, brillo::Any(guid), &error));
350  }
351#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
352  // Ensure that EAP properties cannot be set on services with no EAP
353  // credentials.  Use service2_ here since we're have some code in
354  // ServiceTest::SetUp() that fiddles with service_->eap_.
355  {
356    Error error;
357    string eap("eap eep eip!");
358    EXPECT_FALSE(service2_->mutable_store()->SetAnyProperty(
359        kEapMethodProperty, brillo::Any(eap), &error));
360    ASSERT_TRUE(error.IsFailure());
361    EXPECT_EQ(Error::kInvalidProperty, error.type());
362    // Now plumb in eap credentials, and try again.
363    service2_->SetEapCredentials(new EapCredentials());
364    EXPECT_TRUE(service2_->mutable_store()->SetAnyProperty(
365        kEapMethodProperty, brillo::Any(eap), &error));
366  }
367#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
368  // Ensure that an attempt to write a R/O property returns InvalidArgs error.
369  {
370    Error error;
371    EXPECT_FALSE(service_->mutable_store()->SetAnyProperty(
372        kConnectableProperty, PropertyStoreTest::kBoolV,  &error));
373    ASSERT_TRUE(error.IsFailure());
374    EXPECT_EQ(Error::kInvalidArguments, error.type());
375  }
376  {
377    bool auto_connect = true;
378    Error error;
379    EXPECT_TRUE(service_->mutable_store()->SetAnyProperty(
380        kAutoConnectProperty, brillo::Any(auto_connect), &error));
381  }
382  // Ensure that we can perform a trivial set of the Name property (to its
383  // current value) but an attempt to set the property to a different value
384  // fails.
385  {
386    Error error;
387    EXPECT_FALSE(service_->mutable_store()->SetAnyProperty(
388        kNameProperty, brillo::Any(GetFriendlyName()), &error));
389    EXPECT_FALSE(error.IsFailure());
390  }
391  {
392    Error error;
393    EXPECT_FALSE(service_->mutable_store()->SetAnyProperty(
394        kNameProperty, PropertyStoreTest::kStringV, &error));
395    ASSERT_TRUE(error.IsFailure());
396    EXPECT_EQ(Error::kInvalidArguments, error.type());
397  }
398}
399
400TEST_F(ServiceTest, GetLoadableStorageIdentifier) {
401  NiceMock<MockStore> storage;
402  EXPECT_CALL(storage, ContainsGroup(storage_id_))
403      .WillOnce(Return(false))
404      .WillOnce(Return(true));
405  EXPECT_EQ("", service_->GetLoadableStorageIdentifier(storage));
406  EXPECT_EQ(storage_id_, service_->GetLoadableStorageIdentifier(storage));
407}
408
409TEST_F(ServiceTest, IsLoadableFrom) {
410  NiceMock<MockStore> storage;
411  EXPECT_CALL(storage, ContainsGroup(storage_id_))
412      .WillOnce(Return(false))
413      .WillOnce(Return(true));
414  EXPECT_FALSE(service_->IsLoadableFrom(storage));
415  EXPECT_TRUE(service_->IsLoadableFrom(storage));
416}
417
418#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
419class ServiceWithOnEapCredentialsChangedOverride : public ServiceUnderTest {
420 public:
421  ServiceWithOnEapCredentialsChangedOverride(
422      ControlInterface* control_interface,
423      EventDispatcher* dispatcher,
424      Metrics* metrics,
425      Manager* manager,
426      EapCredentials* eap)
427      : ServiceUnderTest(control_interface, dispatcher, metrics, manager) {
428    SetEapCredentials(eap);
429  }
430  void OnEapCredentialsChanged(Service::UpdateCredentialsReason) override {
431    SetHasEverConnected(false);
432  }
433};
434#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
435
436TEST_F(ServiceTest, Load) {
437#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
438  MockEapCredentials* eap = new MockEapCredentials();  // Owned by |service|.
439  scoped_refptr<ServiceWithOnEapCredentialsChangedOverride> service(
440      new ServiceWithOnEapCredentialsChangedOverride(control_interface(),
441                                                     dispatcher(),
442                                                     metrics(),
443                                                     &mock_manager_,
444                                                     eap));
445#else
446  scoped_refptr<ServiceUnderTest> service(
447      new ServiceUnderTest(control_interface(),
448                           dispatcher(),
449                           metrics(),
450                           &mock_manager_));
451#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
452
453  NiceMock<MockStore> storage;
454  EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
455  const string kCheckPortal("check-portal");
456  const string kGUID("guid");
457  const bool kHasEverConnected = true;
458  const int kPriority = 20;
459  const string kProxyConfig("proxy-config");
460  const string kUIData("ui-data");
461  EXPECT_CALL(storage, GetString(storage_id_, _, _)).Times(AnyNumber());
462  EXPECT_CALL(storage, GetInt(storage_id_, _, _)).Times(AnyNumber());
463  EXPECT_CALL(storage, GetString(storage_id_, Service::kStorageCheckPortal, _))
464      .WillRepeatedly(DoAll(SetArgumentPointee<2>(kCheckPortal), Return(true)));
465  EXPECT_CALL(storage, GetString(storage_id_, Service::kStorageGUID, _))
466      .WillRepeatedly(DoAll(SetArgumentPointee<2>(kGUID), Return(true)));
467  EXPECT_CALL(storage, GetInt(storage_id_, Service::kStoragePriority, _))
468      .WillRepeatedly(DoAll(SetArgumentPointee<2>(kPriority), Return(true)));
469  EXPECT_CALL(storage, GetString(storage_id_, Service::kStorageProxyConfig, _))
470      .WillRepeatedly(DoAll(SetArgumentPointee<2>(kProxyConfig), Return(true)));
471  EXPECT_CALL(storage, GetString(storage_id_, Service::kStorageUIData, _))
472      .WillRepeatedly(DoAll(SetArgumentPointee<2>(kUIData), Return(true)));
473  EXPECT_CALL(storage, GetBool(storage_id_, _, _)).Times(AnyNumber());
474  EXPECT_CALL(storage,
475              GetBool(storage_id_, Service::kStorageSaveCredentials, _));
476  EXPECT_CALL(storage,
477              GetBool(storage_id_, Service::kStorageHasEverConnected, _))
478      .WillRepeatedly(DoAll(SetArgumentPointee<2>(kHasEverConnected),
479                            Return(true)));
480#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
481  EXPECT_CALL(*eap, Load(&storage, storage_id_));
482#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
483  MockDhcpProperties* dhcp_props = new MockDhcpProperties();
484  service->dhcp_properties_.reset(dhcp_props);
485  EXPECT_CALL(*dhcp_props, Load(&storage, storage_id_));
486
487  EXPECT_TRUE(service->Load(&storage));
488  EXPECT_EQ(kCheckPortal, service->check_portal_);
489  EXPECT_EQ(kGUID, service->guid_);
490  EXPECT_TRUE(service->has_ever_connected_);
491  EXPECT_EQ(kProxyConfig, service->proxy_config_);
492  EXPECT_EQ(kUIData, service->ui_data_);
493
494  Mock::VerifyAndClearExpectations(&storage);
495#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
496  Mock::VerifyAndClearExpectations(eap_);
497#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
498  Mock::VerifyAndClearExpectations(dhcp_props);
499
500  // Assure that parameters are set to default if not available in the profile.
501  EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
502  EXPECT_CALL(storage, GetBool(storage_id_, _, _))
503      .WillRepeatedly(Return(false));
504  EXPECT_CALL(storage, GetString(storage_id_, _, _))
505      .WillRepeatedly(Return(false));
506  EXPECT_CALL(storage, GetInt(storage_id_, _, _))
507      .WillRepeatedly(Return(false));
508#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
509  EXPECT_CALL(*eap, Load(&storage, storage_id_));
510#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
511  EXPECT_CALL(*dhcp_props, Load(&storage, storage_id_));
512
513  EXPECT_TRUE(service->Load(&storage));
514  EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
515  EXPECT_EQ("", service->guid_);
516  EXPECT_EQ("", service->proxy_config_);
517  EXPECT_EQ("", service->ui_data_);
518
519  // has_ever_connected_ flag will reset when EAP credential changes.
520#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
521  EXPECT_FALSE(service->has_ever_connected_);
522#else
523  EXPECT_TRUE(service->has_ever_connected_);
524#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
525}
526
527TEST_F(ServiceTest, LoadFail) {
528  StrictMock<MockStore> storage;
529  EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
530  EXPECT_FALSE(service_->Load(&storage));
531}
532
533TEST_F(ServiceTest, LoadAutoConnect) {
534  NiceMock<MockStore> storage;
535  EXPECT_CALL(storage, ContainsGroup(storage_id_))
536      .WillRepeatedly(Return(true));
537  EXPECT_CALL(storage, GetBool(storage_id_, _, _))
538      .WillRepeatedly(Return(false));
539  EXPECT_CALL(storage, GetString(storage_id_, _, _))
540      .WillRepeatedly(Return(false));
541  EXPECT_CALL(storage, GetInt(storage_id_, _, _))
542      .WillRepeatedly(Return(false));
543#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
544  EXPECT_CALL(*eap_, Load(&storage, storage_id_)).Times(AnyNumber());
545#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
546
547  std::unique_ptr<MockDhcpProperties> dhcp_props(new MockDhcpProperties());
548  EXPECT_CALL(*dhcp_props.get(), Load(&storage, storage_id_)).Times(AnyNumber());
549  service_->dhcp_properties_ = std::move(dhcp_props);
550
551  // Three of each expectation so we can test Favorite == unset, false, true.
552  EXPECT_CALL(storage, GetBool(storage_id_, Service::kStorageAutoConnect, _))
553      .WillOnce(Return(false))
554      .WillOnce(Return(false))
555      .WillOnce(Return(false))
556      .WillOnce(DoAll(SetArgumentPointee<2>(false), Return(true)))
557      .WillOnce(DoAll(SetArgumentPointee<2>(false), Return(true)))
558      .WillOnce(DoAll(SetArgumentPointee<2>(false), Return(true)))
559      .WillOnce(DoAll(SetArgumentPointee<2>(true), Return(true)))
560      .WillOnce(DoAll(SetArgumentPointee<2>(true), Return(true)))
561      .WillOnce(DoAll(SetArgumentPointee<2>(true), Return(true)));
562  EXPECT_CALL(storage, GetBool(storage_id_, Service::kStorageFavorite, _))
563      .WillOnce(Return(false))
564      .WillOnce(DoAll(SetArgumentPointee<2>(false), Return(true)))
565      .WillOnce(DoAll(SetArgumentPointee<2>(true), Return(true)))
566      .WillOnce(Return(false))
567      .WillOnce(DoAll(SetArgumentPointee<2>(false), Return(true)))
568      .WillOnce(DoAll(SetArgumentPointee<2>(true), Return(true)))
569      .WillOnce(Return(false))
570      .WillOnce(DoAll(SetArgumentPointee<2>(false), Return(true)))
571      .WillOnce(DoAll(SetArgumentPointee<2>(true), Return(true)));
572
573  // AutoConnect is unset, Favorite is unset.
574  EXPECT_TRUE(service_->Load(&storage));
575  EXPECT_FALSE(service_->auto_connect());
576  EXPECT_FALSE(service_->retain_auto_connect());
577
578  // AutoConnect is unset, Favorite is false.
579  EXPECT_TRUE(service_->Load(&storage));
580  EXPECT_FALSE(service_->auto_connect());
581  EXPECT_FALSE(service_->retain_auto_connect());
582
583  // AutoConnect is unset, Favorite is true.
584  EXPECT_TRUE(service_->Load(&storage));
585  EXPECT_FALSE(service_->auto_connect());
586  EXPECT_TRUE(service_->retain_auto_connect());
587
588  // AutoConnect is false, Favorite is unset.
589  EXPECT_TRUE(service_->Load(&storage));
590  EXPECT_FALSE(service_->auto_connect());
591  EXPECT_TRUE(service_->retain_auto_connect());
592
593  // AutoConnect is false, Favorite is false.
594  EXPECT_TRUE(service_->Load(&storage));
595  EXPECT_FALSE(service_->auto_connect());
596  EXPECT_FALSE(service_->retain_auto_connect());
597
598  // AutoConnect is false, Favorite is true.
599  EXPECT_TRUE(service_->Load(&storage));
600  EXPECT_FALSE(service_->auto_connect());
601  EXPECT_TRUE(service_->retain_auto_connect());
602
603  // AutoConnect is true, Favorite is unset.
604  EXPECT_TRUE(service_->Load(&storage));
605  EXPECT_TRUE(service_->auto_connect());
606  EXPECT_TRUE(service_->retain_auto_connect());
607
608  // AutoConnect is true, Favorite is false (invalid case).
609  EXPECT_TRUE(service_->Load(&storage));
610  EXPECT_TRUE(service_->auto_connect());
611  EXPECT_FALSE(service_->retain_auto_connect());
612
613  // AutoConnect is true, Favorite is true.
614  EXPECT_TRUE(service_->Load(&storage));
615  EXPECT_TRUE(service_->auto_connect());
616  EXPECT_TRUE(service_->retain_auto_connect());
617}
618
619TEST_F(ServiceTest, SaveString) {
620  MockStore storage;
621  static const char kKey[] = "test-key";
622  static const char kData[] = "test-data";
623  EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
624      .WillOnce(Return(true));
625  service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
626}
627
628TEST_F(ServiceTest, SaveStringCrypted) {
629  MockStore storage;
630  static const char kKey[] = "test-key";
631  static const char kData[] = "test-data";
632  EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
633      .WillOnce(Return(true));
634  service_->SaveString(&storage, storage_id_, kKey, kData, true, true);
635}
636
637TEST_F(ServiceTest, SaveStringDontSave) {
638  MockStore storage;
639  static const char kKey[] = "test-key";
640  EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
641      .WillOnce(Return(true));
642  service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
643}
644
645TEST_F(ServiceTest, SaveStringEmpty) {
646  MockStore storage;
647  static const char kKey[] = "test-key";
648  EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
649      .WillOnce(Return(true));
650  service_->SaveString(&storage, storage_id_, kKey, "", true, true);
651}
652
653TEST_F(ServiceTest, Save) {
654  NiceMock<MockStore> storage;
655  EXPECT_CALL(storage, SetString(storage_id_, _, _))
656      .Times(AtLeast(1))
657      .WillRepeatedly(Return(true));
658  EXPECT_CALL(storage, DeleteKey(storage_id_, _))
659      .Times(AtLeast(1))
660      .WillRepeatedly(Return(true));
661  EXPECT_CALL(storage, DeleteKey(storage_id_, Service::kStorageFavorite))
662      .WillOnce(Return(true));
663  EXPECT_CALL(storage, DeleteKey(storage_id_, Service::kStorageAutoConnect))
664      .WillOnce(Return(true));
665  EXPECT_CALL(storage, SetBool(storage_id_, _, _)).Times(AnyNumber());
666  EXPECT_CALL(storage,
667              SetBool(storage_id_,
668                      Service::kStorageSaveCredentials,
669                      service_->save_credentials()));
670#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
671  EXPECT_CALL(*eap_, Save(&storage, storage_id_, true));
672#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
673  std::unique_ptr<MockDhcpProperties> dhcp_props(new MockDhcpProperties());
674  EXPECT_CALL(*dhcp_props.get(), Save(&storage, storage_id_));
675  service_->dhcp_properties_ = std::move(dhcp_props);
676  EXPECT_TRUE(service_->Save(&storage));
677}
678
679TEST_F(ServiceTest, RetainAutoConnect) {
680  NiceMock<MockStore> storage;
681  EXPECT_CALL(storage, SetString(storage_id_, _, _))
682      .Times(AtLeast(1))
683      .WillRepeatedly(Return(true));
684  EXPECT_CALL(storage, DeleteKey(storage_id_, _))
685      .Times(AtLeast(1))
686      .WillRepeatedly(Return(true));
687  EXPECT_CALL(storage, DeleteKey(storage_id_, Service::kStorageFavorite))
688      .Times(2);
689  EXPECT_CALL(storage, DeleteKey(storage_id_, Service::kStorageAutoConnect))
690      .Times(0);
691  EXPECT_CALL(storage, SetBool(storage_id_, _, _)).Times(AnyNumber());
692#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
693  EXPECT_CALL(*eap_, Save(&storage, storage_id_, true)).Times(2);
694#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
695
696  // AutoConnect flag set true.
697  service_->EnableAndRetainAutoConnect();
698  EXPECT_CALL(storage,
699              SetBool(storage_id_, Service::kStorageAutoConnect, true));
700  EXPECT_TRUE(service_->Save(&storage));
701
702  // AutoConnect flag set false.
703  EXPECT_CALL(storage,
704              SetBool(storage_id_, Service::kStorageAutoConnect, false));
705  service_->SetAutoConnect(false);
706  EXPECT_TRUE(service_->Save(&storage));
707}
708
709TEST_F(ServiceTest, HasEverConnectedSavedToProfile) {
710  NiceMock<MockStore> storage;
711  EXPECT_CALL(storage, SetString(storage_id_, _, _))
712      .Times(AtLeast(1))
713      .WillRepeatedly(Return(true));
714  EXPECT_CALL(storage, DeleteKey(storage_id_, _))
715      .Times(AtLeast(1))
716      .WillRepeatedly(Return(true));
717  EXPECT_CALL(storage,
718              DeleteKey(storage_id_, Service::kStorageHasEverConnected))
719      .Times(0);
720  EXPECT_CALL(storage, SetBool(storage_id_, _, _)).Times(AnyNumber());
721#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
722  EXPECT_CALL(*eap_, Save(&storage, storage_id_, true)).Times(2);
723#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
724
725  // HasEverConnected flag set true.
726  service_->SetHasEverConnected(true);
727  EXPECT_CALL(storage,
728              SetBool(storage_id_, Service::kStorageHasEverConnected, true));
729  EXPECT_TRUE(service_->Save(&storage));
730
731  // HasEverConnected flag set false.
732  EXPECT_CALL(storage,
733              SetBool(storage_id_, Service::kStorageHasEverConnected, false));
734  service_->SetHasEverConnected(false);
735  EXPECT_TRUE(service_->Save(&storage));
736}
737
738TEST_F(ServiceTest, Unload) {
739  NiceMock<MockStore> storage;
740  EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
741  static const string string_value("value");
742  EXPECT_CALL(storage, GetString(storage_id_, _, _))
743      .Times(AtLeast(1))
744      .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
745  EXPECT_CALL(storage, GetBool(storage_id_, _, _))
746      .Times(AtLeast(1))
747      .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
748  EXPECT_FALSE(service_->explicitly_disconnected_);
749  service_->explicitly_disconnected_ = true;
750  EXPECT_FALSE(service_->has_ever_connected_);
751#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
752  EXPECT_CALL(*eap_, Load(&storage, storage_id_));
753#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
754  ASSERT_TRUE(service_->Load(&storage));
755  // TODO(pstew): Only two string properties in the service are tested as
756  // a sentinel that properties are being set and reset at the right times.
757  // However, since property load/store is essentially a manual process,
758  // it is error prone and should either be exhaustively unit-tested or
759  // a generic framework for registering loaded/stored properties should
760  // be created. crbug.com/207798
761  EXPECT_EQ(string_value, service_->ui_data_);
762  EXPECT_EQ(string_value, service_->guid_);
763  EXPECT_FALSE(service_->explicitly_disconnected_);
764  EXPECT_TRUE(service_->has_ever_connected_);
765  service_->explicitly_disconnected_ = true;
766#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
767  EXPECT_CALL(*eap_, Reset());
768#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
769  service_->Unload();
770  EXPECT_EQ(string(""), service_->ui_data_);
771  EXPECT_EQ(string(""), service_->guid_);
772  EXPECT_FALSE(service_->explicitly_disconnected_);
773  EXPECT_FALSE(service_->has_ever_connected_);
774}
775
776TEST_F(ServiceTest, State) {
777  EXPECT_EQ(Service::kStateIdle, service_->state());
778  EXPECT_EQ(Service::kStateIdle, GetPreviousState());
779  EXPECT_EQ(Service::kFailureUnknown, service_->failure());
780  const string unknown_error(
781      Service::ConnectFailureToString(Service::kFailureUnknown));
782  EXPECT_EQ(unknown_error, service_->error());
783
784  EXPECT_CALL(*GetAdaptor(),
785              EmitStringChanged(kStateProperty, _)).Times(6);
786  EXPECT_CALL(*GetAdaptor(),
787              EmitStringChanged(kErrorProperty, _)).Times(4);
788  EXPECT_CALL(mock_manager_, UpdateService(IsRefPtrTo(service_)));
789  service_->SetState(Service::kStateConnected);
790  EXPECT_EQ(Service::kStateIdle, GetPreviousState());
791  // A second state change shouldn't cause another update
792  service_->SetState(Service::kStateConnected);
793  EXPECT_EQ(Service::kStateConnected, service_->state());
794  EXPECT_EQ(Service::kStateIdle, GetPreviousState());
795  EXPECT_EQ(Service::kFailureUnknown, service_->failure());
796  EXPECT_TRUE(service_->has_ever_connected_);
797
798  EXPECT_CALL(mock_manager_, UpdateService(IsRefPtrTo(service_)));
799  service_->SetFailure(Service::kFailureOutOfRange);
800  EXPECT_TRUE(service_->IsFailed());
801  EXPECT_GT(service_->failed_time_, 0);
802  EXPECT_GT(service_->previous_error_serial_number_, 0);
803  EXPECT_EQ(Service::kStateFailure, service_->state());
804  EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
805  const string out_of_range_error(
806      Service::ConnectFailureToString(Service::kFailureOutOfRange));
807  EXPECT_EQ(out_of_range_error, service_->error());
808  EXPECT_EQ(out_of_range_error, service_->previous_error_);
809
810  EXPECT_CALL(mock_manager_, UpdateService(IsRefPtrTo(service_)));
811  service_->SetState(Service::kStateConnected);
812  EXPECT_FALSE(service_->IsFailed());
813  EXPECT_EQ(service_->failed_time_, 0);
814  EXPECT_EQ(unknown_error, service_->error());
815  EXPECT_EQ(out_of_range_error, service_->previous_error_);
816  EXPECT_GT(service_->previous_error_serial_number_, 0);
817
818  EXPECT_CALL(mock_manager_, UpdateService(IsRefPtrTo(service_)));
819  service_->SetFailureSilent(Service::kFailurePinMissing);
820  EXPECT_TRUE(service_->IsFailed());
821  EXPECT_GT(service_->failed_time_, 0);
822  EXPECT_GT(service_->previous_error_serial_number_, 0);
823  EXPECT_EQ(Service::kStateIdle, service_->state());
824  EXPECT_EQ(Service::kFailurePinMissing, service_->failure());
825  const string pin_missing_error(
826      Service::ConnectFailureToString(Service::kFailurePinMissing));
827  EXPECT_EQ(pin_missing_error, service_->error());
828  EXPECT_EQ(pin_missing_error, service_->previous_error_);
829
830  // If the Service has a Profile, the profile should be saved when
831  // the service enters kStateConnected. (The case where the service
832  // doesn't have a profile is tested above.)
833  MockProfileRefPtr mock_profile(
834      new MockProfile(control_interface(), metrics(), &mock_manager_));
835  NiceMock<MockStore> storage;
836  service_->set_profile(mock_profile);
837  service_->has_ever_connected_ = false;
838  EXPECT_CALL(mock_manager_, UpdateService(IsRefPtrTo(service_)));
839  EXPECT_CALL(*mock_profile, GetConstStorage())
840      .WillOnce(Return(&storage));
841  EXPECT_CALL(*mock_profile, UpdateService(IsRefPtrTo(service_)));
842  service_->SetState(Service::kStateConnected);
843  EXPECT_TRUE(service_->has_ever_connected_);
844  service_->set_profile(nullptr);  // Break reference cycle.
845
846  // Similar to the above, but emulate an emphemeral profile, which
847  // has no storage. We can't update the service in the profile, but
848  // we should not crash.
849  service_->state_ = Service::kStateIdle;  // Skips state change logic.
850  service_->set_profile(mock_profile);
851  service_->has_ever_connected_ = false;
852  EXPECT_CALL(mock_manager_, UpdateService(IsRefPtrTo(service_)));
853  EXPECT_CALL(*mock_profile, GetConstStorage()).WillOnce(Return(nullptr));
854  service_->SetState(Service::kStateConnected);
855  EXPECT_TRUE(service_->has_ever_connected_);
856  service_->set_profile(nullptr);  // Break reference cycle.
857}
858
859TEST_F(ServiceTest, PortalDetectionFailure) {
860  EXPECT_CALL(*GetAdaptor(),
861              EmitStringChanged(kPortalDetectionFailedPhaseProperty,
862                                kPortalDetectionPhaseDns)).Times(1);
863  EXPECT_CALL(*GetAdaptor(),
864              EmitStringChanged(kPortalDetectionFailedStatusProperty,
865                                kPortalDetectionStatusTimeout)).Times(1);
866  service_->SetPortalDetectionFailure(kPortalDetectionPhaseDns,
867                                      kPortalDetectionStatusTimeout);
868  EXPECT_EQ(kPortalDetectionPhaseDns,
869            service_->portal_detection_failure_phase_);
870  EXPECT_EQ(kPortalDetectionStatusTimeout,
871            service_->portal_detection_failure_status_);
872}
873
874TEST_F(ServiceTest, StateResetAfterFailure) {
875  service_->SetFailure(Service::kFailureOutOfRange);
876  EXPECT_EQ(Service::kStateFailure, service_->state());
877  Error error;
878  service_->Connect(&error, "in test");
879  EXPECT_EQ(Service::kStateIdle, service_->state());
880  EXPECT_EQ(Service::kFailureUnknown, service_->failure());
881
882  service_->SetState(Service::kStateConnected);
883  service_->Connect(&error, "in test");
884  EXPECT_EQ(Service::kStateConnected, service_->state());
885}
886
887TEST_F(ServiceTest, UserInitiatedConnectionResult) {
888  service_->technology_ = Technology::kWifi;
889  Error error;
890  // User-initiated connection attempt succeed.
891  service_->SetState(Service::kStateIdle);
892  service_->UserInitiatedConnect(&error);
893  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionResult(
894      Metrics::kMetricWifiUserInitiatedConnectionResult,
895      Metrics::kUserInitiatedConnectionResultSuccess));
896  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionFailureReason(_, _))
897      .Times(0);
898  service_->SetState(Service::kStateConnected);
899  Mock::VerifyAndClearExpectations(metrics());
900
901  // User-initiated connection attempt failed.
902  service_->SetState(Service::kStateIdle);
903  service_->UserInitiatedConnect(&error);
904  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionResult(
905      Metrics::kMetricWifiUserInitiatedConnectionResult,
906      Metrics::kUserInitiatedConnectionResultFailure));
907  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionFailureReason(
908      Metrics::kMetricWifiUserInitiatedConnectionFailureReason,
909      Service::kFailureDHCP));
910  service_->SetFailure(Service::kFailureDHCP);
911  Mock::VerifyAndClearExpectations(metrics());
912
913  // User-initiated connection attempt aborted.
914  service_->SetState(Service::kStateIdle);
915  service_->UserInitiatedConnect(&error);
916  service_->SetState(Service::kStateAssociating);
917  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionResult(
918      Metrics::kMetricWifiUserInitiatedConnectionResult,
919      Metrics::kUserInitiatedConnectionResultAborted));
920  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionFailureReason(_, _))
921      .Times(0);
922  service_->SetState(Service::kStateIdle);
923  Mock::VerifyAndClearExpectations(metrics());
924
925  // No metric reporting for other state transition.
926  service_->SetState(Service::kStateIdle);
927  service_->UserInitiatedConnect(&error);
928  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionResult(_, _)).Times(0);
929  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionFailureReason(_, _))
930      .Times(0);
931  service_->SetState(Service::kStateAssociating);
932  service_->SetState(Service::kStateConfiguring);
933  Mock::VerifyAndClearExpectations(metrics());
934
935  // No metric reporting for non-user-initiated connection.
936  service_->SetState(Service::kStateIdle);
937  service_->Connect(&error, "in test");
938  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionResult(_, _)).Times(0);
939  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionFailureReason(_, _))
940      .Times(0);
941  service_->SetState(Service::kStateConnected);
942  Mock::VerifyAndClearExpectations(metrics());
943
944  // No metric reporting for other technology.
945  service_->technology_ = Technology::kCellular;
946  service_->SetState(Service::kStateIdle);
947  service_->UserInitiatedConnect(&error);
948  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionResult(_, _)).Times(0);
949  EXPECT_CALL(*metrics(), NotifyUserInitiatedConnectionFailureReason(_, _))
950      .Times(0);
951  service_->SetFailure(Service::kFailureDHCP);
952  Mock::VerifyAndClearExpectations(metrics());
953}
954
955TEST_F(ServiceTest, ActivateCellularModem) {
956  ResultCallback callback =
957      Bind(&ServiceTest::TestCallback, Unretained(this));
958  EXPECT_CALL(*this, TestCallback(_)).Times(0);
959  Error error;
960  service_->ActivateCellularModem("Carrier", &error, callback);
961  EXPECT_TRUE(error.IsFailure());
962}
963
964TEST_F(ServiceTest, CompleteCellularActivation) {
965  Error error;
966  service_->CompleteCellularActivation(&error);
967  EXPECT_EQ(Error::kNotSupported, error.type());
968}
969
970TEST_F(ServiceTest, EnableAndRetainAutoConnect) {
971  EXPECT_FALSE(service_->retain_auto_connect());
972  EXPECT_FALSE(service_->auto_connect());
973
974  service_->EnableAndRetainAutoConnect();
975  EXPECT_TRUE(service_->retain_auto_connect());
976  EXPECT_TRUE(service_->auto_connect());
977}
978
979TEST_F(ServiceTest, ReRetainAutoConnect) {
980  service_->EnableAndRetainAutoConnect();
981  EXPECT_TRUE(service_->retain_auto_connect());
982  EXPECT_TRUE(service_->auto_connect());
983
984  service_->SetAutoConnect(false);
985  service_->EnableAndRetainAutoConnect();
986  EXPECT_TRUE(service_->retain_auto_connect());
987  EXPECT_FALSE(service_->auto_connect());
988}
989
990TEST_F(ServiceTest, IsAutoConnectable) {
991  const char* reason = nullptr;
992  service_->SetConnectable(true);
993
994  // Services with non-primary connectivity technologies should not auto-connect
995  // when the system is offline.
996  EXPECT_EQ(Technology::kUnknown, service_->technology());
997  EXPECT_CALL(mock_manager_, IsConnected()).WillOnce(Return(false));
998  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
999  EXPECT_STREQ(Service::kAutoConnOffline, reason);
1000
1001  service_->technology_ = Technology::kEthernet;
1002  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1003
1004  // We should not auto-connect to a Service that a user has
1005  // deliberately disconnected.
1006  Error error;
1007  service_->UserInitiatedDisconnect(&error);
1008  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1009  EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
1010
1011  // But if the Service is reloaded, it is eligible for auto-connect
1012  // again.
1013  NiceMock<MockStore> storage;
1014  EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
1015#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
1016  EXPECT_CALL(*eap_, Load(&storage, storage_id_));
1017#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
1018  EXPECT_TRUE(service_->Load(&storage));
1019  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1020
1021  // A deliberate Connect should also re-enable auto-connect.
1022  service_->UserInitiatedDisconnect(&error);
1023  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1024  service_->Connect(&error, "in test");
1025  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1026
1027  // A non-user initiated Disconnect doesn't change anything.
1028  service_->Disconnect(&error, "in test");
1029  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1030
1031  // A resume also re-enables auto-connect.
1032  service_->UserInitiatedDisconnect(&error);
1033  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1034  service_->OnAfterResume();
1035  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1036
1037  service_->SetState(Service::kStateConnected);
1038  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1039  EXPECT_STREQ(Service::kAutoConnConnected, reason);
1040
1041  service_->SetState(Service::kStateAssociating);
1042  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1043  EXPECT_STREQ(Service::kAutoConnConnecting, reason);
1044
1045  service_->SetState(Service::kStateIdle);
1046  EXPECT_CALL(mock_manager_, IsTechnologyAutoConnectDisabled(
1047                                 service_->technology_)).WillOnce(Return(true));
1048  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1049  EXPECT_STREQ(Service::kAutoConnTechnologyNotConnectable, reason);
1050}
1051
1052TEST_F(ServiceTest, AutoConnectLogging) {
1053  ScopedMockLog log;
1054  EXPECT_CALL(log, Log(_, _, _));
1055  service_->SetConnectable(true);
1056
1057  ScopeLogger::GetInstance()->EnableScopesByName("+service");
1058  ScopeLogger::GetInstance()->set_verbose_level(1);
1059  service_->SetState(Service::kStateConnected);
1060  EXPECT_CALL(log, Log(-1, _, HasSubstr(Service::kAutoConnConnected)));
1061  service_->AutoConnect();
1062
1063  ScopeLogger::GetInstance()->EnableScopesByName("-service");
1064  ScopeLogger::GetInstance()->set_verbose_level(0);
1065  EXPECT_CALL(log, Log(logging::LOG_INFO, _,
1066                       HasSubstr(Service::kAutoConnNotConnectable)));
1067  service_->SetConnectable(false);
1068  service_->AutoConnect();
1069}
1070
1071
1072TEST_F(AllMockServiceTest, AutoConnectWithFailures) {
1073  const char* reason;
1074  service_->SetConnectable(true);
1075  service_->technology_ = Technology::kEthernet;
1076  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1077
1078  // The very first AutoConnect() doesn't trigger any throttling.
1079  EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
1080  service_->AutoConnect();
1081  Mock::VerifyAndClearExpectations(&dispatcher_);
1082  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1083
1084  // The second call does trigger some throttling.
1085  EXPECT_CALL(dispatcher_, PostDelayedTask(_,
1086      Service::kMinAutoConnectCooldownTimeMilliseconds));
1087  service_->AutoConnect();
1088  Mock::VerifyAndClearExpectations(&dispatcher_);
1089  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1090  EXPECT_STREQ(Service::kAutoConnThrottled, reason);
1091
1092  // Calling AutoConnect() again before the cooldown terminates does not change
1093  // the timeout.
1094  EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
1095  service_->AutoConnect();
1096  Mock::VerifyAndClearExpectations(&dispatcher_);
1097  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1098  EXPECT_STREQ(Service::kAutoConnThrottled, reason);
1099
1100  // Once the timeout expires, we can AutoConnect() again.
1101  service_->ReEnableAutoConnectTask();
1102  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1103
1104  // Timeouts increase exponentially.
1105  uint64_t next_cooldown_time = service_->auto_connect_cooldown_milliseconds_;
1106  EXPECT_EQ(next_cooldown_time,
1107            Service::kAutoConnectCooldownBackoffFactor *
1108            Service::kMinAutoConnectCooldownTimeMilliseconds);
1109  while (next_cooldown_time <=
1110         Service::kMaxAutoConnectCooldownTimeMilliseconds) {
1111    EXPECT_CALL(dispatcher_, PostDelayedTask(_, next_cooldown_time));
1112    service_->AutoConnect();
1113    Mock::VerifyAndClearExpectations(&dispatcher_);
1114    EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1115    EXPECT_STREQ(Service::kAutoConnThrottled, reason);
1116    service_->ReEnableAutoConnectTask();
1117    next_cooldown_time *= Service::kAutoConnectCooldownBackoffFactor;
1118  }
1119
1120  // Once we hit our cap, future timeouts are the same.
1121  for (int32_t i = 0; i < 2; i++) {
1122    EXPECT_CALL(dispatcher_, PostDelayedTask(_,
1123        Service::kMaxAutoConnectCooldownTimeMilliseconds));
1124    service_->AutoConnect();
1125    Mock::VerifyAndClearExpectations(&dispatcher_);
1126    EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1127    EXPECT_STREQ(Service::kAutoConnThrottled, reason);
1128    service_->ReEnableAutoConnectTask();
1129  }
1130
1131  // Connecting successfully resets our cooldown.
1132  service_->SetState(Service::kStateConnected);
1133  service_->SetState(Service::kStateIdle);
1134  reason = "";
1135  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1136  EXPECT_STREQ("", reason);
1137  EXPECT_EQ(service_->auto_connect_cooldown_milliseconds_, 0);
1138
1139  // But future AutoConnects behave as before
1140  EXPECT_CALL(dispatcher_, PostDelayedTask(_,
1141      Service::kMinAutoConnectCooldownTimeMilliseconds)).Times(1);
1142  service_->AutoConnect();
1143  service_->AutoConnect();
1144  Mock::VerifyAndClearExpectations(&dispatcher_);
1145  EXPECT_FALSE(service_->IsAutoConnectable(&reason));
1146  EXPECT_STREQ(Service::kAutoConnThrottled, reason);
1147
1148  // Cooldowns are forgotten if we go through a suspend/resume cycle.
1149  service_->OnAfterResume();
1150  reason = "";
1151  EXPECT_TRUE(service_->IsAutoConnectable(&reason));
1152  EXPECT_STREQ("", reason);
1153}
1154
1155TEST_F(ServiceTest, ConfigureBadProperty) {
1156  KeyValueStore args;
1157  args.SetString("XXXInvalid", "Value");
1158  Error error;
1159  service_->Configure(args, &error);
1160  EXPECT_FALSE(error.IsSuccess());
1161}
1162
1163TEST_F(ServiceTest, ConfigureBoolProperty) {
1164  service_->EnableAndRetainAutoConnect();
1165  service_->SetAutoConnect(false);
1166  ASSERT_FALSE(service_->auto_connect());
1167  KeyValueStore args;
1168  args.SetBool(kAutoConnectProperty, true);
1169  Error error;
1170  service_->Configure(args, &error);
1171  EXPECT_TRUE(error.IsSuccess());
1172  EXPECT_TRUE(service_->auto_connect());
1173}
1174
1175TEST_F(ServiceTest, ConfigureStringProperty) {
1176  const string kGuid0 = "guid_zero";
1177  const string kGuid1 = "guid_one";
1178  service_->SetGuid(kGuid0, nullptr);
1179  ASSERT_EQ(kGuid0, service_->guid());
1180  KeyValueStore args;
1181  args.SetString(kGuidProperty, kGuid1);
1182  Error error;
1183  service_->Configure(args, &error);
1184  EXPECT_TRUE(error.IsSuccess());
1185  EXPECT_EQ(kGuid1, service_->guid());
1186}
1187
1188TEST_F(ServiceTest, ConfigureStringsProperty) {
1189  const vector<string> kStrings0{ "string0", "string1" };
1190  const vector<string> kStrings1{ "string2", "string3" };
1191  service_->set_strings(kStrings0);
1192  ASSERT_EQ(kStrings0, service_->strings());
1193  KeyValueStore args;
1194  args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings1);
1195  Error error;
1196  service_->Configure(args, &error);
1197  EXPECT_TRUE(error.IsSuccess());
1198  EXPECT_EQ(kStrings1, service_->strings());
1199}
1200
1201#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
1202TEST_F(ServiceTest, ConfigureEapStringProperty) {
1203  MockEapCredentials* eap = new MockEapCredentials();
1204  service2_->SetEapCredentials(eap);  // Passes ownership.
1205
1206  const string kEAPManagement0 = "management_zero";
1207  const string kEAPManagement1 = "management_one";
1208  service2_->SetEAPKeyManagement(kEAPManagement0);
1209
1210  EXPECT_CALL(*eap, key_management())
1211      .WillOnce(ReturnRef(kEAPManagement0));
1212  ASSERT_EQ(kEAPManagement0, service2_->GetEAPKeyManagement());
1213  KeyValueStore args;
1214  EXPECT_CALL(*eap, SetKeyManagement(kEAPManagement1, _));
1215  args.SetString(kEapKeyMgmtProperty, kEAPManagement1);
1216  Error error;
1217  service2_->Configure(args, &error);
1218  EXPECT_TRUE(error.IsSuccess());
1219}
1220#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
1221
1222TEST_F(ServiceTest, ConfigureIntProperty) {
1223  const int kPriority0 = 100;
1224  const int kPriority1 = 200;
1225  service_->SetPriority(kPriority0, nullptr);
1226  ASSERT_EQ(kPriority0, service_->priority());
1227  KeyValueStore args;
1228  args.SetInt(kPriorityProperty, kPriority1);
1229  Error error;
1230  service_->Configure(args, &error);
1231  EXPECT_TRUE(error.IsSuccess());
1232  EXPECT_EQ(kPriority1, service_->priority());
1233}
1234
1235TEST_F(ServiceTest, ConfigureIgnoredProperty) {
1236  service_->EnableAndRetainAutoConnect();
1237  service_->SetAutoConnect(false);
1238  ASSERT_FALSE(service_->auto_connect());
1239  KeyValueStore args;
1240  args.SetBool(kAutoConnectProperty, true);
1241  Error error;
1242  service_->IgnoreParameterForConfigure(kAutoConnectProperty);
1243  service_->Configure(args, &error);
1244  EXPECT_TRUE(error.IsSuccess());
1245  EXPECT_FALSE(service_->auto_connect());
1246}
1247
1248TEST_F(ServiceTest, ConfigureProfileProperty) {
1249  // Ensure that the Profile property is always ignored.
1250  KeyValueStore args;
1251  args.SetString(kProfileProperty, "profile");
1252  Error error;
1253  EXPECT_CALL(mock_manager_, SetProfileForService(_, _, _)).Times(0);
1254  service_->Configure(args, &error);
1255  EXPECT_TRUE(error.IsSuccess());
1256}
1257
1258TEST_F(ServiceTest, ConfigureKeyValueStoreProperty) {
1259  KeyValueStore key_value_store0;
1260  key_value_store0.SetBool("key0", true);
1261  KeyValueStore key_value_store1;
1262  key_value_store1.SetInt("key1", 1);
1263  service_->SetKeyValueStore(key_value_store0, NULL);
1264  ASSERT_EQ(key_value_store0, service_->GetKeyValueStore(NULL));
1265  KeyValueStore args;
1266  args.SetKeyValueStore(
1267      ServiceUnderTest::kKeyValueStoreProperty, key_value_store1);
1268  Error error;
1269  service_->Configure(args, &error);
1270  EXPECT_TRUE(error.IsSuccess());
1271  EXPECT_EQ(key_value_store1, service_->GetKeyValueStore(NULL));
1272}
1273
1274TEST_F(ServiceTest, DoPropertiesMatch) {
1275  service_->SetAutoConnect(false);
1276  const string kGUID0 = "guid_zero";
1277  const string kGUID1 = "guid_one";
1278  service_->SetGuid(kGUID0, nullptr);
1279  const uint32_t kPriority0 = 100;
1280  const uint32_t kPriority1 = 200;
1281  service_->SetPriority(kPriority0, nullptr);
1282  const vector<string> kStrings0{ "string0", "string1" };
1283  const vector<string> kStrings1{ "string2", "string3" };
1284  service_->set_strings(kStrings0);
1285  KeyValueStore key_value_store0;
1286  key_value_store0.SetBool("key0", true);
1287  KeyValueStore key_value_store1;
1288  key_value_store1.SetInt("key1", 1);
1289  service_->SetKeyValueStore(key_value_store0, NULL);
1290
1291  {
1292    KeyValueStore args;
1293    args.SetString(kGuidProperty, kGUID0);
1294    args.SetBool(kAutoConnectProperty, false);
1295    args.SetInt(kPriorityProperty, kPriority0);
1296    args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings0);
1297    args.SetKeyValueStore(ServiceUnderTest::kKeyValueStoreProperty,
1298                          key_value_store0);
1299    EXPECT_TRUE(service_->DoPropertiesMatch(args));
1300  }
1301  {
1302    KeyValueStore args;
1303    args.SetString(kGuidProperty, kGUID1);
1304    args.SetBool(kAutoConnectProperty, false);
1305    args.SetInt(kPriorityProperty, kPriority0);
1306    args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings0);
1307    args.SetKeyValueStore(ServiceUnderTest::kKeyValueStoreProperty,
1308                          key_value_store0);
1309    EXPECT_FALSE(service_->DoPropertiesMatch(args));
1310  }
1311  {
1312    KeyValueStore args;
1313    args.SetString(kGuidProperty, kGUID0);
1314    args.SetBool(kAutoConnectProperty, true);
1315    args.SetInt(kPriorityProperty, kPriority0);
1316    args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings0);
1317    args.SetKeyValueStore(ServiceUnderTest::kKeyValueStoreProperty,
1318                          key_value_store0);
1319    EXPECT_FALSE(service_->DoPropertiesMatch(args));
1320  }
1321  {
1322    KeyValueStore args;
1323    args.SetString(kGuidProperty, kGUID0);
1324    args.SetBool(kAutoConnectProperty, false);
1325    args.SetInt(kPriorityProperty, kPriority1);
1326    args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings0);
1327    args.SetKeyValueStore(ServiceUnderTest::kKeyValueStoreProperty,
1328                          key_value_store0);
1329    EXPECT_FALSE(service_->DoPropertiesMatch(args));
1330  }
1331  {
1332    KeyValueStore args;
1333    args.SetString(kGuidProperty, kGUID0);
1334    args.SetBool(kAutoConnectProperty, false);
1335    args.SetInt(kPriorityProperty, kPriority0);
1336    args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings1);
1337    args.SetKeyValueStore(ServiceUnderTest::kKeyValueStoreProperty,
1338                          key_value_store0);
1339    EXPECT_FALSE(service_->DoPropertiesMatch(args));
1340  }
1341  {
1342    KeyValueStore args;
1343    args.SetString(kGuidProperty, kGUID0);
1344    args.SetBool(kAutoConnectProperty, false);
1345    args.SetInt(kPriorityProperty, kPriority0);
1346    args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings0);
1347    args.SetKeyValueStore(ServiceUnderTest::kKeyValueStoreProperty,
1348                          key_value_store1);
1349    EXPECT_FALSE(service_->DoPropertiesMatch(args));
1350  }
1351}
1352
1353TEST_F(ServiceTest, IsRemembered) {
1354  service_->set_profile(nullptr);
1355  EXPECT_CALL(mock_manager_, IsServiceEphemeral(_)).Times(0);
1356  EXPECT_FALSE(service_->IsRemembered());
1357
1358  scoped_refptr<MockProfile> profile(
1359      new StrictMock<MockProfile>(control_interface(), metrics(), manager()));
1360  service_->set_profile(profile);
1361  EXPECT_CALL(mock_manager_, IsServiceEphemeral(IsRefPtrTo(service_)))
1362     .WillOnce(Return(true))
1363     .WillOnce(Return(false));
1364  EXPECT_FALSE(service_->IsRemembered());
1365  EXPECT_TRUE(service_->IsRemembered());
1366}
1367
1368TEST_F(ServiceTest, IsDependentOn) {
1369  EXPECT_FALSE(service_->IsDependentOn(nullptr));
1370
1371  std::unique_ptr<MockDeviceInfo> mock_device_info(
1372      new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
1373                                   &mock_manager_));
1374  scoped_refptr<MockConnection> mock_connection0(
1375      new NiceMock<MockConnection>(mock_device_info.get()));
1376  scoped_refptr<MockConnection> mock_connection1(
1377      new NiceMock<MockConnection>(mock_device_info.get()));
1378
1379  service_->connection_ = mock_connection0;
1380  EXPECT_CALL(*mock_connection0, GetLowerConnection())
1381      .WillRepeatedly(Return(mock_connection1));
1382  EXPECT_CALL(*mock_connection1, GetLowerConnection())
1383      .WillRepeatedly(Return(ConnectionRefPtr()));
1384  EXPECT_FALSE(service_->IsDependentOn(nullptr));
1385
1386  scoped_refptr<ServiceUnderTest> service1 =
1387      new ServiceUnderTest(control_interface(),
1388                           dispatcher(),
1389                           metrics(),
1390                           &mock_manager_);
1391  EXPECT_FALSE(service_->IsDependentOn(service1));
1392
1393  service1->connection_ = mock_connection0;
1394  EXPECT_FALSE(service_->IsDependentOn(service1));
1395
1396  service1->connection_ = mock_connection1;
1397  EXPECT_TRUE(service_->IsDependentOn(service1));
1398
1399  service_->connection_ = mock_connection1;
1400  service1->connection_ = nullptr;
1401  EXPECT_FALSE(service_->IsDependentOn(service1));
1402
1403  service_->connection_ = nullptr;
1404}
1405
1406TEST_F(ServiceTest, OnPropertyChanged) {
1407  scoped_refptr<MockProfile> profile(
1408      new StrictMock<MockProfile>(control_interface(), metrics(), manager()));
1409  service_->set_profile(nullptr);
1410  // Expect no crash.
1411  service_->OnPropertyChanged("");
1412
1413  // Expect no call to Update if the profile has no storage.
1414  service_->set_profile(profile);
1415  EXPECT_CALL(*profile, UpdateService(_)).Times(0);
1416  EXPECT_CALL(*profile, GetConstStorage()).WillOnce(Return(nullptr));
1417  service_->OnPropertyChanged("");
1418
1419  // Expect call to Update if the profile has storage.
1420  EXPECT_CALL(*profile, UpdateService(_)).Times(1);
1421  NiceMock<MockStore> storage;
1422  EXPECT_CALL(*profile, GetConstStorage()).WillOnce(Return(&storage));
1423  service_->OnPropertyChanged("");
1424}
1425
1426
1427TEST_F(ServiceTest, RecheckPortal) {
1428  service_->state_ = Service::kStateIdle;
1429  EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
1430  service_->OnPropertyChanged(kCheckPortalProperty);
1431
1432  service_->state_ = Service::kStatePortal;
1433  EXPECT_CALL(mock_manager_, RecheckPortalOnService(IsRefPtrTo(service_)))
1434      .Times(1);
1435  service_->OnPropertyChanged(kCheckPortalProperty);
1436
1437  service_->state_ = Service::kStateConnected;
1438  EXPECT_CALL(mock_manager_, RecheckPortalOnService(IsRefPtrTo(service_)))
1439      .Times(1);
1440  service_->OnPropertyChanged(kProxyConfigProperty);
1441
1442  service_->state_ = Service::kStateOnline;
1443  EXPECT_CALL(mock_manager_, RecheckPortalOnService(IsRefPtrTo(service_)))
1444      .Times(1);
1445  service_->OnPropertyChanged(kCheckPortalProperty);
1446
1447  service_->state_ = Service::kStatePortal;
1448  EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
1449  service_->OnPropertyChanged(kEapKeyIdProperty);
1450}
1451
1452TEST_F(ServiceTest, SetCheckPortal) {
1453  {
1454    Error error;
1455    service_->SetCheckPortal("false", &error);
1456    EXPECT_TRUE(error.IsSuccess());
1457    EXPECT_EQ(Service::kCheckPortalFalse, service_->check_portal_);
1458  }
1459  {
1460    Error error;
1461    service_->SetCheckPortal("true", &error);
1462    EXPECT_TRUE(error.IsSuccess());
1463    EXPECT_EQ(Service::kCheckPortalTrue, service_->check_portal_);
1464  }
1465  {
1466    Error error;
1467    service_->SetCheckPortal("auto", &error);
1468    EXPECT_TRUE(error.IsSuccess());
1469    EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
1470  }
1471  {
1472    Error error;
1473    service_->SetCheckPortal("xxx", &error);
1474    EXPECT_FALSE(error.IsSuccess());
1475    EXPECT_EQ(Error::kInvalidArguments, error.type());
1476    EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
1477  }
1478}
1479
1480TEST_F(ServiceTest, SetFriendlyName) {
1481  EXPECT_EQ(service_->unique_name_, service_->friendly_name_);
1482  ServiceMockAdaptor* adaptor = GetAdaptor();
1483
1484  EXPECT_CALL(*adaptor, EmitStringChanged(_, _)).Times(0);
1485  service_->SetFriendlyName(service_->unique_name_);
1486  EXPECT_EQ(service_->unique_name_, service_->friendly_name_);
1487
1488  EXPECT_CALL(*adaptor, EmitStringChanged(kNameProperty,
1489                                          "Test Name 1"));
1490  service_->SetFriendlyName("Test Name 1");
1491  EXPECT_EQ("Test Name 1", service_->friendly_name_);
1492
1493  EXPECT_CALL(*adaptor, EmitStringChanged(_, _)).Times(0);
1494  service_->SetFriendlyName("Test Name 1");
1495  EXPECT_EQ("Test Name 1", service_->friendly_name_);
1496
1497  EXPECT_CALL(*adaptor, EmitStringChanged(kNameProperty,
1498                                          "Test Name 2"));
1499  service_->SetFriendlyName("Test Name 2");
1500  EXPECT_EQ("Test Name 2", service_->friendly_name_);
1501}
1502
1503TEST_F(ServiceTest, SetConnectableFull) {
1504  EXPECT_FALSE(service_->connectable());
1505
1506  ServiceMockAdaptor* adaptor = GetAdaptor();
1507
1508  EXPECT_CALL(*adaptor, EmitBoolChanged(_, _)).Times(0);
1509  EXPECT_CALL(mock_manager_, HasService(_)).Times(0);
1510  service_->SetConnectableFull(false);
1511  EXPECT_FALSE(service_->connectable());
1512
1513  EXPECT_CALL(*adaptor, EmitBoolChanged(kConnectableProperty, true));
1514  EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(false));
1515  EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
1516  service_->SetConnectableFull(true);
1517  EXPECT_TRUE(service_->connectable());
1518
1519  EXPECT_CALL(*adaptor, EmitBoolChanged(kConnectableProperty, false));
1520  EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
1521  EXPECT_CALL(mock_manager_, UpdateService(_));
1522  service_->SetConnectableFull(false);
1523  EXPECT_FALSE(service_->connectable());
1524
1525  EXPECT_CALL(*adaptor, EmitBoolChanged(kConnectableProperty, true));
1526  EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
1527              EXPECT_CALL(mock_manager_, UpdateService(_));
1528  service_->SetConnectableFull(true);
1529  EXPECT_TRUE(service_->connectable());
1530}
1531
1532#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
1533class WriteOnlyServicePropertyTest : public ServiceTest {};
1534TEST_P(WriteOnlyServicePropertyTest, PropertyWriteOnly) {
1535  // Use a real EapCredentials instance since the base Service class
1536  // contains no write-only properties.
1537  EapCredentials eap;
1538  eap.InitPropertyStore(service_->mutable_store());
1539
1540  string property(GetParam().Get<string>());
1541  Error error;
1542  EXPECT_FALSE(service_->store().GetStringProperty(property, nullptr, &error));
1543  EXPECT_EQ(Error::kPermissionDenied, error.type());
1544}
1545
1546INSTANTIATE_TEST_CASE_P(
1547    WriteOnlyServicePropertyTestInstance,
1548    WriteOnlyServicePropertyTest,
1549    Values(
1550        brillo::Any(string(kEapPrivateKeyPasswordProperty)),
1551        brillo::Any(string(kEapPasswordProperty))));
1552#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
1553
1554TEST_F(ServiceTest, GetIPConfigRpcIdentifier) {
1555  {
1556    Error error;
1557    EXPECT_EQ(control_interface()->NullRPCIdentifier(),
1558              service_->GetIPConfigRpcIdentifier(&error));
1559    EXPECT_EQ(Error::kNotFound, error.type());
1560  }
1561
1562  std::unique_ptr<MockDeviceInfo> mock_device_info(
1563      new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
1564                                   &mock_manager_));
1565  scoped_refptr<MockConnection> mock_connection(
1566      new NiceMock<MockConnection>(mock_device_info.get()));
1567
1568  service_->connection_ = mock_connection;
1569
1570  {
1571    Error error;
1572    const string empty_string;
1573    EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
1574        .WillOnce(ReturnRef(empty_string));
1575    EXPECT_EQ(control_interface()->NullRPCIdentifier(),
1576              service_->GetIPConfigRpcIdentifier(&error));
1577    EXPECT_EQ(Error::kNotFound, error.type());
1578  }
1579
1580  {
1581    Error error;
1582    const string nonempty_string("/ipconfig/path");
1583    EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
1584        .WillOnce(ReturnRef(nonempty_string));
1585    EXPECT_EQ(nonempty_string, service_->GetIPConfigRpcIdentifier(&error));
1586    EXPECT_EQ(Error::kSuccess, error.type());
1587  }
1588
1589  // Assure orderly destruction of the Connection before DeviceInfo.
1590  service_->connection_ = nullptr;
1591  mock_connection = nullptr;
1592  mock_device_info.reset();
1593}
1594
1595#if !defined(DISABLE_WIFI) || !defined(DISABLE_WIRED_8021X)
1596class ServiceWithMockOnEapCredentialsChanged : public ServiceUnderTest {
1597 public:
1598  ServiceWithMockOnEapCredentialsChanged(ControlInterface* control_interface,
1599                                         EventDispatcher* dispatcher,
1600                                         Metrics* metrics,
1601                                         Manager* manager)
1602      : ServiceUnderTest(control_interface, dispatcher, metrics, manager),
1603        is_8021x_(false) {}
1604  MOCK_METHOD1(OnEapCredentialsChanged, void(Service::UpdateCredentialsReason));
1605  virtual bool Is8021x() const { return is_8021x_; }
1606  void set_is_8021x(bool is_8021x) { is_8021x_ = is_8021x; }
1607
1608 private:
1609  bool is_8021x_;
1610};
1611
1612TEST_F(ServiceTest, SetEAPCredentialsOverRPC) {
1613  scoped_refptr<ServiceWithMockOnEapCredentialsChanged> service(
1614      new ServiceWithMockOnEapCredentialsChanged(control_interface(),
1615                                                 dispatcher(),
1616                                                 metrics(),
1617                                                 &mock_manager_));
1618  string eap_credential_properties[] = {
1619      kEapAnonymousIdentityProperty,
1620      kEapCertIdProperty,
1621      kEapClientCertProperty,
1622      kEapIdentityProperty,
1623      kEapKeyIdProperty,
1624      kEapPasswordProperty,
1625      kEapPinProperty,
1626      kEapPrivateKeyProperty,
1627      kEapPrivateKeyPasswordProperty
1628  };
1629  string eap_non_credential_properties[] = {
1630      kEapCaCertIdProperty,
1631      kEapCaCertNssProperty,
1632      kEapMethodProperty,
1633      kEapPhase2AuthProperty,
1634      kEapUseSystemCasProperty
1635  };
1636  // While this is not an 802.1x-based service, none of these property
1637  // changes should cause a call to set_eap().
1638  EXPECT_CALL(*service, OnEapCredentialsChanged(_)).Times(0);
1639  for (size_t i = 0; i < arraysize(eap_credential_properties); ++i)
1640    service->OnPropertyChanged(eap_credential_properties[i]);
1641  for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
1642    service->OnPropertyChanged(eap_non_credential_properties[i]);
1643  service->OnPropertyChanged(kEapKeyMgmtProperty);
1644
1645  service->set_is_8021x(true);
1646
1647  // When this is an 802.1x-based service, set_eap should be called for
1648  // all credential-carrying properties.
1649  for (size_t i = 0; i < arraysize(eap_credential_properties); ++i) {
1650    EXPECT_CALL(*service,
1651                OnEapCredentialsChanged(
1652                    Service::kReasonPropertyUpdate)).Times(1);
1653    service->OnPropertyChanged(eap_credential_properties[i]);
1654    Mock::VerifyAndClearExpectations(service.get());
1655  }
1656
1657  // The key management property is a special case.  While not strictly
1658  // a credential, it can change which credentials are used.  Therefore it
1659  // should also trigger a call to set_eap();
1660  EXPECT_CALL(*service,
1661              OnEapCredentialsChanged(Service::kReasonPropertyUpdate)).Times(1);
1662  service->OnPropertyChanged(kEapKeyMgmtProperty);
1663  Mock::VerifyAndClearExpectations(service.get());
1664
1665  EXPECT_CALL(*service, OnEapCredentialsChanged(_)).Times(0);
1666  for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
1667    service->OnPropertyChanged(eap_non_credential_properties[i]);
1668}
1669
1670TEST_F(ServiceTest, Certification) {
1671  EXPECT_FALSE(service_->remote_certification_.size());
1672
1673  ScopedMockLog log;
1674  EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
1675                       HasSubstr("exceeds our maximum"))).Times(2);
1676  string kSubject("foo");
1677  EXPECT_FALSE(service_->AddEAPCertification(
1678      kSubject, Service::kEAPMaxCertificationElements));
1679  EXPECT_FALSE(service_->AddEAPCertification(
1680      kSubject, Service::kEAPMaxCertificationElements + 1));
1681  EXPECT_FALSE(service_->remote_certification_.size());
1682  Mock::VerifyAndClearExpectations(&log);
1683
1684  EXPECT_CALL(log,
1685              Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
1686      .Times(1);
1687  EXPECT_TRUE(service_->AddEAPCertification(
1688      kSubject, Service::kEAPMaxCertificationElements - 1));
1689  Mock::VerifyAndClearExpectations(&log);
1690  EXPECT_EQ(Service::kEAPMaxCertificationElements,
1691      service_->remote_certification_.size());
1692  for (size_t i = 0; i < Service::kEAPMaxCertificationElements - 1; ++i) {
1693      EXPECT_TRUE(service_->remote_certification_[i].empty());
1694  }
1695  EXPECT_EQ(kSubject, service_->remote_certification_[
1696      Service::kEAPMaxCertificationElements - 1]);
1697
1698  // Re-adding the same name in the same position should not generate a log.
1699  EXPECT_CALL(log, Log(_, _, _)).Times(0);
1700  EXPECT_TRUE(service_->AddEAPCertification(
1701      kSubject, Service::kEAPMaxCertificationElements - 1));
1702
1703  // Replacing the item should generate a log message.
1704  EXPECT_CALL(log,
1705              Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
1706      .Times(1);
1707  EXPECT_TRUE(service_->AddEAPCertification(
1708      kSubject + "x", Service::kEAPMaxCertificationElements - 1));
1709
1710  service_->ClearEAPCertification();
1711  EXPECT_TRUE(service_->remote_certification_.empty());
1712}
1713#endif  // DISABLE_WIFI || DISABLE_WIRED_8021X
1714
1715TEST_F(ServiceTest, NoteDisconnectEventIdle) {
1716  Timestamp timestamp;
1717  EXPECT_CALL(time_, GetNow()).Times(7).WillRepeatedly((Return(timestamp)));
1718  SetStateField(Service::kStateOnline);
1719  EXPECT_FALSE(service_->HasRecentConnectionIssues());
1720  service_->SetState(Service::kStateIdle);
1721  // The transition Online->Idle is not an event.
1722  EXPECT_FALSE(service_->HasRecentConnectionIssues());
1723  service_->SetState(Service::kStateFailure);
1724  // The transition Online->Idle->Failure is a connection drop.
1725  EXPECT_TRUE(service_->HasRecentConnectionIssues());
1726}
1727
1728TEST_F(ServiceTest, NoteDisconnectEventOnSetStateFailure) {
1729  Timestamp timestamp;
1730  EXPECT_CALL(time_, GetNow()).Times(5).WillRepeatedly((Return(timestamp)));
1731  SetStateField(Service::kStateOnline);
1732  EXPECT_FALSE(service_->HasRecentConnectionIssues());
1733  service_->SetState(Service::kStateFailure);
1734  EXPECT_TRUE(service_->HasRecentConnectionIssues());
1735}
1736
1737TEST_F(ServiceTest, NoteDisconnectEventOnSetFailureSilent) {
1738  Timestamp timestamp;
1739  EXPECT_CALL(time_, GetNow()).Times(5).WillRepeatedly((Return(timestamp)));
1740  SetStateField(Service::kStateConfiguring);
1741  EXPECT_FALSE(service_->HasRecentConnectionIssues());
1742  service_->SetFailureSilent(Service::kFailureEAPAuthentication);
1743  EXPECT_TRUE(service_->HasRecentConnectionIssues());
1744}
1745
1746TEST_F(ServiceTest, NoteDisconnectEventNonEvent) {
1747  EXPECT_CALL(time_, GetNow()).Times(0);
1748
1749  // Explicit disconnect is a non-event.
1750  SetStateField(Service::kStateOnline);
1751  SetExplicitlyDisconnected(true);
1752  NoteDisconnectEvent();
1753  EXPECT_TRUE(GetDisconnects()->Empty());
1754  EXPECT_TRUE(GetMisconnects()->Empty());
1755
1756  // Failure to idle transition is a non-event.
1757  SetStateField(Service::kStateFailure);
1758  SetExplicitlyDisconnected(false);
1759  NoteDisconnectEvent();
1760  EXPECT_TRUE(GetDisconnects()->Empty());
1761  EXPECT_TRUE(GetMisconnects()->Empty());
1762
1763  // Disconnect while manager is stopped is a non-event.
1764  SetStateField(Service::kStateOnline);
1765  SetManagerRunning(false);
1766  NoteDisconnectEvent();
1767  EXPECT_TRUE(GetDisconnects()->Empty());
1768  EXPECT_TRUE(GetMisconnects()->Empty());
1769
1770  // Disconnect while suspending is a non-event.
1771  SetManagerRunning(true);
1772  SetSuspending(true);
1773  NoteDisconnectEvent();
1774  EXPECT_TRUE(GetDisconnects()->Empty());
1775  EXPECT_TRUE(GetMisconnects()->Empty());
1776}
1777
1778TEST_F(ServiceTest, NoteDisconnectEventDisconnectOnce) {
1779  const int kNow = 5;
1780  EXPECT_FALSE(service_->explicitly_disconnected());
1781  SetStateField(Service::kStateOnline);
1782  EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, kNow, "")));
1783  NoteDisconnectEvent();
1784  ASSERT_EQ(1, GetDisconnects()->Size());
1785  EXPECT_EQ(kNow, GetDisconnects()->Front().monotonic.tv_sec);
1786  EXPECT_TRUE(GetMisconnects()->Empty());
1787
1788  Mock::VerifyAndClearExpectations(&time_);
1789  EXPECT_CALL(time_, GetNow()).Times(2).WillRepeatedly(Return(GetTimestamp(
1790      kNow + GetDisconnectsMonitorSeconds() - 1,
1791      kNow + GetDisconnectsMonitorSeconds() - 1,
1792      "")));
1793  EXPECT_TRUE(service_->HasRecentConnectionIssues());
1794  ASSERT_EQ(1, GetDisconnects()->Size());
1795
1796  Mock::VerifyAndClearExpectations(&time_);
1797  EXPECT_CALL(time_, GetNow()).Times(2).WillRepeatedly(Return(GetTimestamp(
1798      kNow + GetDisconnectsMonitorSeconds(),
1799      kNow + GetDisconnectsMonitorSeconds(),
1800      "")));
1801  EXPECT_FALSE(service_->HasRecentConnectionIssues());
1802  ASSERT_TRUE(GetDisconnects()->Empty());
1803}
1804
1805TEST_F(ServiceTest, NoteDisconnectEventMisconnectOnce) {
1806  const int kNow = 7;
1807  EXPECT_FALSE(service_->explicitly_disconnected());
1808  SetStateField(Service::kStateConfiguring);
1809  EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, kNow, "")));
1810  NoteDisconnectEvent();
1811  EXPECT_TRUE(GetDisconnects()->Empty());
1812  ASSERT_EQ(1, GetMisconnects()->Size());
1813  EXPECT_EQ(kNow, GetMisconnects()->Front().monotonic.tv_sec);
1814
1815  Mock::VerifyAndClearExpectations(&time_);
1816  EXPECT_CALL(time_, GetNow()).Times(2).WillRepeatedly(Return(GetTimestamp(
1817      kNow + GetMisconnectsMonitorSeconds() - 1,
1818      kNow + GetMisconnectsMonitorSeconds() - 1,
1819      "")));
1820  EXPECT_TRUE(service_->HasRecentConnectionIssues());
1821  ASSERT_EQ(1, GetMisconnects()->Size());
1822
1823  Mock::VerifyAndClearExpectations(&time_);
1824  EXPECT_CALL(time_, GetNow()).Times(2).WillRepeatedly(Return(GetTimestamp(
1825      kNow + GetMisconnectsMonitorSeconds(),
1826      kNow + GetMisconnectsMonitorSeconds(),
1827      "")));
1828  EXPECT_FALSE(service_->HasRecentConnectionIssues());
1829  ASSERT_TRUE(GetMisconnects()->Empty());
1830}
1831
1832TEST_F(ServiceTest, NoteDisconnectEventDiscardOld) {
1833  EXPECT_FALSE(service_->explicitly_disconnected());
1834  for (int i = 0; i < 2; i++) {
1835    int now = 0;
1836    EventHistory* events = nullptr;
1837    if (i == 0) {
1838      SetStateField(Service::kStateConnected);
1839      now = GetDisconnectsMonitorSeconds() + 1;
1840      events = GetDisconnects();
1841    } else {
1842      SetStateField(Service::kStateAssociating);
1843      now = GetMisconnectsMonitorSeconds() + 1;
1844      events = GetMisconnects();
1845    }
1846    PushTimestamp(events, 0, 0, "");
1847    PushTimestamp(events, 0, 0, "");
1848    EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(now, now, "")));
1849    NoteDisconnectEvent();
1850    ASSERT_EQ(1, events->Size());
1851    EXPECT_EQ(now, events->Front().monotonic.tv_sec);
1852  }
1853}
1854
1855TEST_F(ServiceTest, NoteDisconnectEventDiscardExcessive) {
1856  EXPECT_FALSE(service_->explicitly_disconnected());
1857  SetStateField(Service::kStateOnline);
1858  for (int i = 0; i < 2 * GetMaxDisconnectEventHistory(); i++) {
1859    PushTimestamp(GetDisconnects(), 0, 0, "");
1860  }
1861  EXPECT_CALL(time_, GetNow()).WillOnce(Return(Timestamp()));
1862  NoteDisconnectEvent();
1863  EXPECT_EQ(GetMaxDisconnectEventHistory(), GetDisconnects()->Size());
1864}
1865
1866TEST_F(ServiceTest, NoteMisconnectEventDiscardExcessive) {
1867  EXPECT_FALSE(service_->explicitly_disconnected());
1868  SetStateField(Service::kStateAssociating);
1869  for (int i = 0; i < 2 * GetMaxMisconnectEventHistory(); i++) {
1870    PushTimestamp(GetMisconnects(), 0, 0, "");
1871  }
1872  EXPECT_CALL(time_, GetNow()).WillOnce(Return(Timestamp()));
1873  NoteDisconnectEvent();
1874  EXPECT_EQ(GetMaxMisconnectEventHistory(), GetMisconnects()->Size());
1875}
1876
1877TEST_F(ServiceTest, DiagnosticsProperties) {
1878  const string kWallClock0 = "2012-12-09T12:41:22.234567-0800";
1879  const string kWallClock1 = "2012-12-31T23:59:59.345678-0800";
1880  Strings values;
1881
1882  PushTimestamp(GetDisconnects(), 0, 0, kWallClock0);
1883  Error unused_error;
1884  ASSERT_TRUE(service_->store().GetStringsProperty(
1885     kDiagnosticsDisconnectsProperty, &values, &unused_error));
1886  ASSERT_EQ(1, values.size());
1887  EXPECT_EQ(kWallClock0, values[0]);
1888
1889  PushTimestamp(GetMisconnects(), 0, 0, kWallClock1);
1890  ASSERT_TRUE(service_->store().GetStringsProperty(
1891      kDiagnosticsMisconnectsProperty, &values, &unused_error));
1892  ASSERT_EQ(1, values.size());
1893  EXPECT_EQ(kWallClock1, values[0]);
1894}
1895
1896TEST_F(ServiceTest, SecurityLevel) {
1897  // Encrypted is better than not.
1898  service_->SetSecurity(Service::kCryptoNone, false, false);
1899  service2_->SetSecurity(Service::kCryptoRc4, false, false);
1900  EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1901
1902  // AES encryption is better than RC4 encryption.
1903  service_->SetSecurity(Service::kCryptoRc4, false, false);
1904  service2_->SetSecurity(Service::kCryptoAes, false, false);
1905  EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1906
1907  // Crypto algorithm is more important than key rotation.
1908  service_->SetSecurity(Service::kCryptoNone, true, false);
1909  service2_->SetSecurity(Service::kCryptoAes, false, false);
1910  EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1911
1912  // Encrypted-but-unauthenticated is better than clear-but-authenticated.
1913  service_->SetSecurity(Service::kCryptoNone, false, true);
1914  service2_->SetSecurity(Service::kCryptoAes, false, false);
1915  EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1916
1917  // For same encryption, prefer key rotation.
1918  service_->SetSecurity(Service::kCryptoRc4, false, false);
1919  service2_->SetSecurity(Service::kCryptoRc4, true, false);
1920  EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1921
1922  // For same encryption, prefer authenticated AP.
1923  service_->SetSecurity(Service::kCryptoRc4, false, false);
1924  service2_->SetSecurity(Service::kCryptoRc4, false, true);
1925  EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1926}
1927
1928TEST_F(ServiceTest, SetErrorDetails) {
1929  EXPECT_EQ(Service::kErrorDetailsNone, service_->error_details());
1930  static const char kDetails[] = "Certificate revoked.";
1931  ServiceMockAdaptor* adaptor = GetAdaptor();
1932  EXPECT_CALL(*adaptor, EmitStringChanged(kErrorDetailsProperty, kDetails));
1933  service_->SetErrorDetails(Service::kErrorDetailsNone);
1934  EXPECT_EQ(Service::kErrorDetailsNone, service_->error_details());
1935  service_->SetErrorDetails(kDetails);
1936  EXPECT_EQ(kDetails, service_->error_details());
1937  service_->SetErrorDetails(kDetails);
1938}
1939
1940TEST_F(ServiceTest, SetAutoConnectFull) {
1941  EXPECT_FALSE(service_->auto_connect());
1942  Error error;
1943  EXPECT_FALSE(GetAutoConnect(&error));
1944  EXPECT_TRUE(error.IsSuccess());
1945
1946  // false -> false
1947  EXPECT_FALSE(service_->retain_auto_connect());
1948  EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
1949  SetAutoConnectFull(false, &error);
1950  EXPECT_TRUE(error.IsSuccess());
1951  EXPECT_FALSE(service_->auto_connect());
1952  EXPECT_TRUE(service_->retain_auto_connect());
1953  EXPECT_FALSE(GetAutoConnect(nullptr));
1954  Mock::VerifyAndClearExpectations(&mock_manager_);
1955
1956  // Clear the |retain_auto_connect_| flag for the next test.
1957  service_->Unload();
1958  ASSERT_FALSE(service_->retain_auto_connect());
1959
1960  // false -> true
1961  EXPECT_CALL(mock_manager_, UpdateService(_)).Times(1);
1962  SetAutoConnectFull(true, &error);
1963  EXPECT_TRUE(error.IsSuccess());
1964  EXPECT_TRUE(service_->auto_connect());
1965  EXPECT_TRUE(GetAutoConnect(nullptr));
1966  EXPECT_TRUE(service_->retain_auto_connect());
1967  Mock::VerifyAndClearExpectations(&mock_manager_);
1968
1969  // Clear the |retain_auto_connect_| flag for the next test.
1970  service_->Unload();
1971  ASSERT_FALSE(service_->retain_auto_connect());
1972
1973  // true -> true
1974  service_->SetAutoConnect(true);
1975  EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
1976  SetAutoConnectFull(true, &error);
1977  EXPECT_TRUE(error.IsSuccess());
1978  EXPECT_TRUE(service_->auto_connect());
1979  EXPECT_TRUE(GetAutoConnect(nullptr));
1980  EXPECT_TRUE(service_->retain_auto_connect());
1981  Mock::VerifyAndClearExpectations(&mock_manager_);
1982
1983  // Clear the |retain_auto_connect_| flag for the next test.
1984  service_->Unload();
1985  ASSERT_FALSE(service_->retain_auto_connect());
1986
1987  // true -> false
1988  service_->SetAutoConnect(true);
1989  EXPECT_CALL(mock_manager_, UpdateService(_)).Times(1);
1990  SetAutoConnectFull(false, &error);
1991  EXPECT_TRUE(error.IsSuccess());
1992  EXPECT_FALSE(service_->auto_connect());
1993  EXPECT_FALSE(GetAutoConnect(nullptr));
1994  EXPECT_TRUE(service_->retain_auto_connect());
1995  Mock::VerifyAndClearExpectations(&mock_manager_);
1996}
1997
1998TEST_F(ServiceTest, SetAutoConnectFullUserUpdatePersists) {
1999  // If the user sets the kAutoConnectProperty explicitly, the preference must
2000  // be persisted, even if the property was not changed.
2001  Error error;
2002  MockProfileRefPtr mock_profile(
2003      new MockProfile(control_interface(), metrics(), &mock_manager_));
2004  NiceMock<MockStore> storage;
2005  service_->set_profile(mock_profile);
2006  service_->SetAutoConnect(true);
2007
2008  EXPECT_CALL(*mock_profile, UpdateService(_));
2009  EXPECT_CALL(*mock_profile, GetConstStorage())
2010      .WillOnce(Return(&storage));
2011  EXPECT_CALL(mock_manager_, IsServiceEphemeral(IsRefPtrTo(service_)))
2012      .WillOnce(Return(false));
2013  EXPECT_FALSE(service_->retain_auto_connect());
2014  SetAutoConnectFull(true, &error);
2015  EXPECT_TRUE(error.IsSuccess());
2016  EXPECT_TRUE(service_->auto_connect());
2017  EXPECT_TRUE(service_->retain_auto_connect());
2018}
2019
2020TEST_F(ServiceTest, ClearAutoConnect) {
2021  EXPECT_FALSE(service_->auto_connect());
2022  Error error;
2023  EXPECT_FALSE(GetAutoConnect(&error));
2024  EXPECT_TRUE(error.IsSuccess());
2025
2026  // unset -> false
2027  EXPECT_FALSE(service_->retain_auto_connect());
2028  EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
2029  ClearAutoConnect(&error);
2030  EXPECT_TRUE(error.IsSuccess());
2031  EXPECT_FALSE(service_->retain_auto_connect());
2032  EXPECT_FALSE(GetAutoConnect(nullptr));
2033  Mock::VerifyAndClearExpectations(&mock_manager_);
2034
2035  // false -> false
2036  SetAutoConnectFull(false, &error);
2037  EXPECT_FALSE(GetAutoConnect(nullptr));
2038  EXPECT_TRUE(service_->retain_auto_connect());
2039  EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
2040  ClearAutoConnect(&error);
2041  EXPECT_TRUE(error.IsSuccess());
2042  EXPECT_FALSE(service_->retain_auto_connect());
2043  EXPECT_FALSE(GetAutoConnect(nullptr));
2044  Mock::VerifyAndClearExpectations(&mock_manager_);
2045
2046  // true -> false
2047  SetAutoConnectFull(true, &error);
2048  EXPECT_TRUE(error.IsSuccess());
2049  EXPECT_TRUE(GetAutoConnect(nullptr));
2050  EXPECT_CALL(mock_manager_, UpdateService(_)).Times(1);
2051  ClearAutoConnect(&error);
2052  EXPECT_FALSE(service_->retain_auto_connect());
2053  EXPECT_FALSE(GetAutoConnect(nullptr));
2054  Mock::VerifyAndClearExpectations(&mock_manager_);
2055}
2056
2057TEST_F(ServiceTest, UniqueAttributes) {
2058  EXPECT_NE(service_->serial_number_, service2_->serial_number_);
2059  EXPECT_NE(service_->unique_name(), service2_->unique_name());
2060}
2061
2062TEST_F(ServiceTest, PropertyChanges) {
2063  TestCommonPropertyChanges(service_, GetAdaptor());
2064  TestAutoConnectPropertyChange(service_, GetAdaptor());
2065}
2066
2067// Custom property setters should return false, and make no changes, if
2068// the new value is the same as the old value.
2069TEST_F(ServiceTest, CustomSetterNoopChange) {
2070  TestCustomSetterNoopChange(service_, &mock_manager_);
2071}
2072
2073TEST_F(ServiceTest, GetTethering) {
2074  Error error;
2075  EXPECT_EQ("", service_->GetTethering(&error));
2076  EXPECT_EQ(Error::kNotSupported, error.type());
2077}
2078
2079class ServiceWithMockOnPropertyChanged : public ServiceUnderTest {
2080 public:
2081  ServiceWithMockOnPropertyChanged(ControlInterface* control_interface,
2082                                   EventDispatcher* dispatcher,
2083                                   Metrics* metrics,
2084                                   Manager* manager)
2085      : ServiceUnderTest(control_interface, dispatcher, metrics, manager) {}
2086  MOCK_METHOD1(OnPropertyChanged, void(const string& property));
2087};
2088
2089TEST_F(ServiceTest, ConfigureServiceTriggersOnPropertyChanged) {
2090  auto service(make_scoped_refptr(
2091      new ServiceWithMockOnPropertyChanged(control_interface(),
2092                                           dispatcher(),
2093                                           metrics(),
2094                                           &mock_manager_)));
2095  KeyValueStore args;
2096  args.SetString(kUIDataProperty, "terpsichorean ejectamenta");
2097  args.SetBool(kSaveCredentialsProperty, false);
2098
2099  // Calling Configure with different values from before triggers a single
2100  // OnPropertyChanged call per property.
2101  EXPECT_CALL(*service, OnPropertyChanged(kUIDataProperty)).Times(1);
2102  EXPECT_CALL(*service, OnPropertyChanged(kSaveCredentialsProperty)).Times(1);
2103  {
2104    Error error;
2105    service->Configure(args, &error);
2106    EXPECT_TRUE(error.IsSuccess());
2107  }
2108  Mock::VerifyAndClearExpectations(service.get());
2109
2110  // Calling Configure with the same values as before should not trigger
2111  // OnPropertyChanged().
2112  EXPECT_CALL(*service, OnPropertyChanged(_)).Times(0);
2113  {
2114    Error error;
2115    service->Configure(args, &error);
2116    EXPECT_TRUE(error.IsSuccess());
2117  }
2118}
2119
2120TEST_F(ServiceTest, ClearExplicitlyDisconnected) {
2121  EXPECT_FALSE(GetExplicitlyDisconnected());
2122  EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
2123  service_->ClearExplicitlyDisconnected();
2124  Mock::VerifyAndClearExpectations(&mock_manager_);
2125
2126  SetExplicitlyDisconnected(true);
2127  EXPECT_CALL(mock_manager_, UpdateService(IsRefPtrTo(service_)));
2128  service_->ClearExplicitlyDisconnected();
2129  Mock::VerifyAndClearExpectations(&mock_manager_);
2130  EXPECT_FALSE(GetExplicitlyDisconnected());
2131}
2132
2133TEST_F(ServiceTest, Compare) {
2134  // Construct our Services so that the string comparison of
2135  // unique_name_ differs from the numerical comparison of
2136  // serial_number_.
2137  vector<scoped_refptr<MockService>> mock_services;
2138  for (size_t i = 0; i < 11; ++i) {
2139    mock_services.push_back(
2140        new NiceMock<MockService>(control_interface(),
2141                                  dispatcher(),
2142                                  metrics(),
2143                                  manager()));
2144  }
2145  scoped_refptr<MockService> service2 = mock_services[2];
2146  scoped_refptr<MockService> service10 = mock_services[10];
2147  mock_services.clear();
2148
2149  // Services should already be sorted by |serial_number_|.
2150  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2151
2152  // Two otherwise equal services should be reordered by strength
2153  service10->SetStrength(1);
2154  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2155
2156  scoped_refptr<MockProfile> profile2(
2157      new MockProfile(control_interface(), metrics(), manager(), ""));
2158  scoped_refptr<MockProfile> profile10(
2159      new MockProfile(control_interface(), metrics(), manager(), ""));
2160
2161  service2->set_profile(profile2);
2162  service10->set_profile(profile10);
2163
2164  // When comparing two services with different profiles, prefer the one
2165  // that is not ephemeral.
2166  EXPECT_CALL(mock_manager_, IsServiceEphemeral(IsRefPtrTo(service2)))
2167      .WillRepeatedly(Return(false));
2168  EXPECT_CALL(mock_manager_, IsServiceEphemeral(IsRefPtrTo(service10)))
2169      .WillRepeatedly(Return(true));
2170  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2171  Mock::VerifyAndClearExpectations(&mock_manager_);
2172
2173  // Prefer the service with the more recently applied profile if neither
2174  // service is ephemeral.
2175  EXPECT_CALL(mock_manager_, IsServiceEphemeral(_))
2176      .WillRepeatedly(Return(false));
2177  EXPECT_CALL(mock_manager_, IsProfileBefore(IsRefPtrTo(profile2),
2178                                             IsRefPtrTo(profile10)))
2179      .WillRepeatedly(Return(true));
2180  EXPECT_CALL(mock_manager_, IsProfileBefore(IsRefPtrTo(profile10),
2181                                             IsRefPtrTo(profile2)))
2182      .WillRepeatedly(Return(false));
2183  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2184
2185  // Security.
2186  service2->SetSecurity(Service::kCryptoAes, true, true);
2187  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2188
2189  // PriorityWithinTechnology.
2190  service10->SetPriorityWithinTechnology(1, nullptr);
2191  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2192  service2->SetPriorityWithinTechnology(2, nullptr);
2193  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2194
2195  // Technology.
2196  EXPECT_CALL(*service2.get(), technology())
2197      .WillRepeatedly(Return((Technology::kWifi)));
2198  EXPECT_CALL(*service10.get(), technology())
2199      .WillRepeatedly(Return(Technology::kEthernet));
2200
2201  technology_order_for_sorting_ = {Technology::kEthernet, Technology::kWifi};
2202  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2203
2204  technology_order_for_sorting_ = {Technology::kWifi, Technology::kEthernet};
2205  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2206
2207  // Priority.
2208  service2->SetPriority(1, nullptr);
2209  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2210  service10->SetPriority(2, nullptr);
2211  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2212
2213  // A service that has been connected before should be considered
2214  // above a service that neither been connected to before nor has
2215  // has managed credentials.
2216  service2->has_ever_connected_ = true;
2217  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2218
2219  // If one service has been connected to before, and the other is managed
2220  // by Chrome they should rank same, so the priority will be considered
2221  // instead.
2222  service10->managed_credentials_ = true;
2223  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2224  service2->SetPriority(3, nullptr);
2225  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2226
2227  // A service with managed credentials should be considered above one that
2228  // has neither been connected to before nor has managed credentials.
2229  service2->has_ever_connected_ = false;
2230  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2231
2232  // Auto-connect.
2233  service2->SetAutoConnect(true);
2234  service10->SetAutoConnect(false);
2235  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2236
2237  // Test is-dependent-on.
2238  EXPECT_CALL(*service10.get(),
2239              IsDependentOn(IsRefPtrTo(service2.get())))
2240      .WillOnce(Return(true))
2241      .WillOnce(Return(false));
2242  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2243  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2244
2245  // It doesn't make sense to have is-dependent-on ranking comparison in any of
2246  // the remaining subtests below.  Reset to the default.
2247  EXPECT_CALL(*service10.get(), IsDependentOn(_)).WillRepeatedly(Return(false));
2248  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2249
2250  // Connectable.
2251  service10->SetConnectable(true);
2252  service2->SetConnectable(false);
2253  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2254
2255  // IsFailed.
2256  EXPECT_CALL(*service2.get(), state())
2257      .WillRepeatedly(Return(Service::kStateIdle));
2258  EXPECT_CALL(*service2.get(), IsFailed())
2259      .WillRepeatedly(Return(false));
2260  EXPECT_CALL(*service10.get(), state())
2261      .WillRepeatedly(Return(Service::kStateFailure));
2262  EXPECT_CALL(*service10.get(), IsFailed())
2263      .WillRepeatedly(Return(true));
2264  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2265
2266  // Connecting.
2267  EXPECT_CALL(*service10.get(), state())
2268      .WillRepeatedly(Return(Service::kStateAssociating));
2269  EXPECT_CALL(*service10.get(), IsConnecting())
2270      .WillRepeatedly(Return(true));
2271  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2272
2273  // Connected-but-portalled preferred over unconnected.
2274  EXPECT_CALL(*service2.get(), state())
2275      .WillRepeatedly(Return(Service::kStatePortal));
2276  EXPECT_CALL(*service2.get(), IsConnected())
2277      .WillRepeatedly(Return(true));
2278  EXPECT_TRUE(DefaultSortingOrderIs(service2, service10));
2279
2280  // Connected preferred over connected-but-portalled.
2281  service10->SetConnectable(false);
2282  service2->SetConnectable(true);
2283  EXPECT_CALL(*service10.get(), state())
2284      .WillRepeatedly(Return(Service::kStateConnected));
2285  EXPECT_CALL(*service10.get(), IsConnected())
2286      .WillRepeatedly(Return(true));
2287  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2288
2289  // Online preferred over just connected.
2290  EXPECT_CALL(*service2.get(), state())
2291      .WillRepeatedly(Return(Service::kStateOnline));
2292  EXPECT_TRUE(DefaultSortingOrderIs(service10, service2));
2293
2294  // Connectivity state ignored if this is specified.
2295  const bool kDoNotCompareConnectivityState = false;
2296  EXPECT_TRUE(SortingOrderIs(service2, service10,
2297                             kDoNotCompareConnectivityState));
2298}
2299
2300}  // namespace shill
2301