• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2012 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/wifi/wifi_service.h"
18 
19 #include <limits>
20 #include <map>
21 #include <set>
22 #include <string>
23 #include <vector>
24 
25 #include <base/strings/stringprintf.h>
26 #include <base/strings/string_number_conversions.h>
27 #include <base/strings/string_util.h>
28 #if defined(__ANDROID__)
29 #include <dbus/service_constants.h>
30 #else
31 #include <chromeos/dbus/service_constants.h>
32 #endif  // __ANDROID__
33 #include <gmock/gmock.h>
34 #include <gtest/gtest.h>
35 
36 #include "shill/event_dispatcher.h"
37 #include "shill/manager.h"
38 #include "shill/metrics.h"
39 #include "shill/mock_adaptors.h"
40 #include "shill/mock_certificate_file.h"
41 #include "shill/mock_control.h"
42 #include "shill/mock_eap_credentials.h"
43 #include "shill/mock_log.h"
44 #include "shill/mock_manager.h"
45 #include "shill/mock_profile.h"
46 #include "shill/mock_service.h"
47 #include "shill/mock_store.h"
48 #include "shill/property_store_unittest.h"
49 #include "shill/refptr_types.h"
50 #include "shill/service_property_change_test.h"
51 #include "shill/supplicant/wpa_supplicant.h"
52 #include "shill/technology.h"
53 #include "shill/tethering.h"
54 #include "shill/wifi/mock_wifi.h"
55 #include "shill/wifi/mock_wifi_provider.h"
56 #include "shill/wifi/wifi_endpoint.h"
57 
58 using base::FilePath;
59 using std::map;
60 using std::set;
61 using std::string;
62 using std::vector;
63 using ::testing::_;
64 using ::testing::AnyNumber;
65 using ::testing::DoAll;
66 using ::testing::EndsWith;
67 using ::testing::HasSubstr;
68 using ::testing::Mock;
69 using ::testing::NiceMock;
70 using ::testing::Return;
71 using ::testing::ReturnRef;
72 using ::testing::SetArgumentPointee;
73 using ::testing::StrEq;
74 using ::testing::StrNe;
75 using ::testing::StrictMock;
76 
77 namespace shill {
78 
79 class WiFiServiceTest : public PropertyStoreTest {
80  public:
WiFiServiceTest()81   WiFiServiceTest()
82       : mock_manager_(control_interface(), dispatcher(), metrics()),
83         wifi_(
84             new NiceMock<MockWiFi>(control_interface(),
85                                    dispatcher(),
86                                    metrics(),
87                                    manager(),
88                                    "wifi",
89                                    fake_mac,
90                                    0)),
91         simple_ssid_(1, 'a'),
92         simple_ssid_string_("a") {}
~WiFiServiceTest()93   virtual ~WiFiServiceTest() {}
94 
95  protected:
96   static const char fake_mac[];
97 
SetMockEap(const WiFiServiceRefPtr & service)98   MockEapCredentials* SetMockEap(
99       const WiFiServiceRefPtr& service) {
100     MockEapCredentials* eap = new MockEapCredentials();
101     service->eap_.reset(eap);  // Passes ownership.
102     return eap;
103   }
CheckConnectable(const string & security,const char * passphrase,bool is_1x_connectable)104   bool CheckConnectable(const string& security, const char* passphrase,
105                         bool is_1x_connectable) {
106     Error error;
107     WiFiServiceRefPtr service = MakeSimpleService(security);
108     if (passphrase)
109       service->SetPassphrase(passphrase, &error);
110     MockEapCredentials* eap = SetMockEap(service);
111     EXPECT_CALL(*eap, IsConnectable())
112         .WillRepeatedly(Return(is_1x_connectable));
113     const string kKeyManagement8021x(WPASupplicant::kKeyManagementIeee8021X);
114     if (security == kSecurityWep && is_1x_connectable) {
115       EXPECT_CALL(*eap, key_management())
116           .WillRepeatedly(ReturnRef(kKeyManagement8021x));
117     }
118     service->OnEapCredentialsChanged(Service::kReasonCredentialsLoaded);
119     return service->connectable();
120   }
MakeEndpoint(const string & ssid,const string & bssid,uint16_t frequency,int16_t signal_dbm,bool has_wpa_property,bool has_rsn_property)121   WiFiEndpoint* MakeEndpoint(const string& ssid, const string& bssid,
122                              uint16_t frequency, int16_t signal_dbm,
123                              bool has_wpa_property, bool has_rsn_property) {
124     return WiFiEndpoint::MakeEndpoint(
125         nullptr, wifi(), ssid, bssid, WPASupplicant::kNetworkModeInfrastructure,
126         frequency, signal_dbm, has_wpa_property, has_rsn_property);
127   }
MakeOpenEndpoint(const string & ssid,const string & bssid,uint16_t frequency,int16_t signal_dbm)128   WiFiEndpoint* MakeOpenEndpoint(const string& ssid, const string& bssid,
129                                  uint16_t frequency, int16_t signal_dbm) {
130     return WiFiEndpoint::MakeOpenEndpoint(
131         nullptr, wifi(), ssid, bssid, WPASupplicant::kNetworkModeInfrastructure,
132         frequency, signal_dbm);
133   }
MakeOpenEndpointWithWiFi(WiFiRefPtr wifi,const string & ssid,const string & bssid,uint16_t frequency,int16_t signal_dbm)134   WiFiEndpoint* MakeOpenEndpointWithWiFi(WiFiRefPtr wifi,
135                                          const string& ssid,
136                                          const string& bssid,
137                                          uint16_t frequency,
138                                          int16_t signal_dbm) {
139     return WiFiEndpoint::MakeOpenEndpoint(
140         nullptr, wifi, ssid, bssid, WPASupplicant::kNetworkModeInfrastructure,
141         frequency, signal_dbm);
142   }
MakeSimpleService(const string & security)143   WiFiServiceRefPtr MakeSimpleService(const string& security) {
144     return new WiFiService(control_interface(),
145                            dispatcher(),
146                            metrics(),
147                            manager(),
148                            &provider_,
149                            simple_ssid_,
150                            kModeManaged,
151                            security,
152                            false);
153   }
MakeGenericService()154   WiFiServiceRefPtr MakeGenericService() {
155     return MakeSimpleService(kSecurityWep);
156   }
SetWiFi(WiFiServiceRefPtr service,WiFiRefPtr wifi)157   void SetWiFi(WiFiServiceRefPtr service, WiFiRefPtr wifi) {
158     service->SetWiFi(wifi);  // Has side-effects.
159   }
SetWiFiForService(WiFiServiceRefPtr service,WiFiRefPtr wifi)160   void SetWiFiForService(WiFiServiceRefPtr service, WiFiRefPtr wifi) {
161     service->wifi_ = wifi;
162   }
MakeServiceWithWiFi(const string & security)163   WiFiServiceRefPtr MakeServiceWithWiFi(const string& security) {
164     WiFiServiceRefPtr service = MakeSimpleService(security);
165     SetWiFiForService(service, wifi_);
166     return service;
167   }
MakeServiceWithMockManager()168   WiFiServiceRefPtr MakeServiceWithMockManager() {
169     return new WiFiService(control_interface(),
170                            dispatcher(),
171                            metrics(),
172                            &mock_manager_,
173                            &provider_,
174                            simple_ssid_,
175                            kModeManaged,
176                            kSecurityNone,
177                            false);
178   }
MakeSimpleWiFi(const string & link_name)179   scoped_refptr<MockWiFi> MakeSimpleWiFi(const string& link_name) {
180     return new NiceMock<MockWiFi>(control_interface(),
181                                   dispatcher(),
182                                   metrics(),
183                                   manager(),
184                                   link_name,
185                                   fake_mac,
186                                   0);
187   }
GetAdaptor(WiFiService * service)188   ServiceMockAdaptor* GetAdaptor(WiFiService* service) {
189     return static_cast<ServiceMockAdaptor*>(service->adaptor());
190   }
TestConfigurePassphrase(const string & security,const char * passphrase)191   Error::Type TestConfigurePassphrase(const string& security,
192                                       const char* passphrase) {
193     WiFiServiceRefPtr service = MakeSimpleService(security);
194     KeyValueStore args;
195     if (passphrase) {
196       args.SetString(kPassphraseProperty, passphrase);
197     }
198     Error error;
199     service->Configure(args, &error);
200     return error.type();
201   }
SetRoamThreshold(WiFiServiceRefPtr service,uint16_t threshold)202   bool SetRoamThreshold(WiFiServiceRefPtr service, uint16_t threshold) {
203     return service->SetRoamThreshold(threshold, nullptr);
204   }
GetRoamThreshold(WiFiServiceRefPtr service) const205   uint16_t GetRoamThreshold(WiFiServiceRefPtr service) const {
206     return service->GetRoamThreshold(nullptr);
207   }
wifi()208   scoped_refptr<MockWiFi> wifi() { return wifi_; }
mock_manager()209   MockManager* mock_manager() { return &mock_manager_; }
provider()210   MockWiFiProvider* provider() { return &provider_; }
GetAnyDeviceAddress()211   string GetAnyDeviceAddress() { return WiFiService::kAnyDeviceAddress; }
simple_ssid()212   const vector<uint8_t>& simple_ssid() { return simple_ssid_; }
simple_ssid_string()213   const string& simple_ssid_string() { return simple_ssid_string_; }
214 
215  private:
216   MockManager mock_manager_;
217   scoped_refptr<MockWiFi> wifi_;
218   MockWiFiProvider provider_;
219   const vector<uint8_t> simple_ssid_;
220   const string simple_ssid_string_;
221 };
222 
223 // static
224 const char WiFiServiceTest::fake_mac[] = "AaBBcCDDeeFF";
225 
226 MATCHER_P3(ContainsWiFiProperties, ssid, mode, security, "") {
227   string hex_ssid = base::HexEncode(ssid.data(), ssid.size());
228   return
229       arg.ContainsString(WiFiService::kStorageType) &&
230       arg.GetString(WiFiService::kStorageType) == kTypeWifi &&
231       arg.ContainsString(WiFiService::kStorageSSID) &&
232       arg.GetString(WiFiService::kStorageSSID) == hex_ssid &&
233       arg.ContainsString(WiFiService::kStorageMode) &&
234       arg.GetString(WiFiService::kStorageMode) == mode &&
235       arg.ContainsString(WiFiService::kStorageSecurityClass) &&
236       arg.GetString(WiFiService::kStorageSecurityClass) == security;
237 }
238 
239 class WiFiServiceSecurityTest : public WiFiServiceTest {
240  public:
TestStorageSecurityIs(WiFiServiceRefPtr wifi_service,const string & security)241   bool TestStorageSecurityIs(WiFiServiceRefPtr wifi_service,
242                              const string& security) {
243     string id = wifi_service->GetStorageIdentifier();
244     size_t mac_pos = id.find(base::ToLowerASCII(GetAnyDeviceAddress()));
245     EXPECT_NE(mac_pos, string::npos);
246     size_t mode_pos = id.find(string(kModeManaged), mac_pos);
247     EXPECT_NE(mode_pos, string::npos);
248     return id.find(string(security), mode_pos) != string::npos;
249   }
250 
251   // Test that a service that is created with security |from_security|
252   // gets by default a storage identifier with |to_security| as its
253   // security component, and that when saved, it sets the Security
254   // property in to |to_security| as well.
TestStorageMapping(const string & from_security,const string & to_security)255   bool TestStorageMapping(const string& from_security,
256                           const string& to_security) {
257     WiFiServiceRefPtr wifi_service = MakeSimpleService(from_security);
258     NiceMock<MockStore> mock_store;
259     EXPECT_CALL(mock_store, SetString(_, _, _)).WillRepeatedly(Return(true));
260     EXPECT_CALL(mock_store,
261                 SetString(_, WiFiService::kStorageSecurity, from_security))
262         .Times(1);
263     EXPECT_CALL(mock_store,
264                 SetString(_, WiFiService::kStorageSecurityClass, to_security))
265         .Times(1);
266     wifi_service->Save(&mock_store);
267     return TestStorageSecurityIs(wifi_service, to_security);
268   }
269 
270   // Test whether a service of type |service_security| can load from a
271   // storage interface containing an entry for |storage_security|.
272   // Make sure the result meets |expectation|.  If |expectation| is
273   // true, also make sure the service storage identifier changes to
274   // match |storage_security|.
TestLoadMapping(const string & service_security,const string & storage_security,bool expectation)275   bool TestLoadMapping(const string& service_security,
276                        const string& storage_security,
277                        bool expectation) {
278     WiFiServiceRefPtr wifi_service = MakeSimpleService(service_security);
279     NiceMock<MockStore> mock_store;
280     EXPECT_CALL(mock_store, GetGroupsWithProperties(_))
281         .WillRepeatedly(Return(set<string>()));
282     const string kStorageId = "storage_id";
283     EXPECT_CALL(mock_store, ContainsGroup(kStorageId))
284         .WillRepeatedly(Return(true));
285     set<string> groups;
286     groups.insert(kStorageId);
287     EXPECT_CALL(mock_store, GetGroupsWithProperties(
288         ContainsWiFiProperties(wifi_service->ssid(),
289                                kModeManaged,
290                                storage_security)))
291         .WillRepeatedly(Return(groups));
292     bool is_loadable = wifi_service->IsLoadableFrom(mock_store);
293     EXPECT_EQ(expectation, is_loadable);
294     bool is_loaded = wifi_service->Load(&mock_store);
295     EXPECT_EQ(expectation, is_loaded);
296     const string expected_identifier(expectation ? kStorageId : "");
297     EXPECT_EQ(expected_identifier,
298               wifi_service->GetLoadableStorageIdentifier(mock_store));
299 
300     if (expectation != is_loadable || expectation != is_loaded) {
301       return false;
302     } else if (!expectation) {
303       return true;
304     } else {
305       return wifi_service->GetStorageIdentifier() == kStorageId;
306     }
307   }
308 };
309 
310 class WiFiServiceUpdateFromEndpointsTest : public WiFiServiceTest {
311  public:
WiFiServiceUpdateFromEndpointsTest()312   WiFiServiceUpdateFromEndpointsTest()
313       : kOkEndpointStrength(WiFiService::SignalToStrength(kOkEndpointSignal)),
314         kBadEndpointStrength(WiFiService::SignalToStrength(kBadEndpointSignal)),
315         kGoodEndpointStrength(
316             WiFiService::SignalToStrength(kGoodEndpointSignal)),
317         service(MakeGenericService()),
318         adaptor(*GetAdaptor(service.get())) {
319     ok_endpoint = MakeOpenEndpoint(
320         simple_ssid_string(), kOkEndpointBssId, kOkEndpointFrequency,
321         kOkEndpointSignal);
322     good_endpoint = MakeOpenEndpoint(
323         simple_ssid_string(), kGoodEndpointBssId, kGoodEndpointFrequency,
324         kGoodEndpointSignal);
325     bad_endpoint = MakeOpenEndpoint(
326         simple_ssid_string(), kBadEndpointBssId, kBadEndpointFrequency,
327         kBadEndpointSignal);
328   }
329 
330  protected:
331   static const uint16_t kOkEndpointFrequency = 2422;
332   static const uint16_t kBadEndpointFrequency = 2417;
333   static const uint16_t kGoodEndpointFrequency = 2412;
334   static const int16_t kOkEndpointSignal = -50;
335   static const int16_t kBadEndpointSignal = -75;
336   static const int16_t kGoodEndpointSignal = -25;
337   static const char* kOkEndpointBssId;
338   static const char* kGoodEndpointBssId;
339   static const char* kBadEndpointBssId;
340   // Can't be both static and const (because initialization requires a
341   // function call). So choose to be just const.
342   const uint8_t kOkEndpointStrength;
343   const uint8_t kBadEndpointStrength;
344   const uint8_t kGoodEndpointStrength;
345   WiFiEndpointRefPtr ok_endpoint;
346   WiFiEndpointRefPtr bad_endpoint;
347   WiFiEndpointRefPtr good_endpoint;
348   WiFiServiceRefPtr service;
349   ServiceMockAdaptor& adaptor;
350 };
351 
352 const char* WiFiServiceUpdateFromEndpointsTest::kOkEndpointBssId =
353     "00:00:00:00:00:01";
354 const char* WiFiServiceUpdateFromEndpointsTest::kGoodEndpointBssId =
355     "00:00:00:00:00:02";
356 const char* WiFiServiceUpdateFromEndpointsTest::kBadEndpointBssId =
357     "00:00:00:00:00:03";
358 
359 class WiFiServiceFixupStorageTest : public WiFiServiceTest {
360  protected:
AddGroup(string group_name)361   void AddGroup(string group_name) {
362     groups_.insert(group_name);
363   }
364 
AddServiceEntry(bool has_type,bool has_mode,bool has_security,bool has_security_class)365   void AddServiceEntry(bool has_type, bool has_mode, bool has_security,
366                        bool has_security_class) {
367     int index = groups_.size();
368     string id = base::StringPrintf("%s_%d_%d_%s_%s", kTypeWifi,
369                                    index, index, kModeManaged,
370                                    kSecurityWpa);
371     AddGroup(id);
372     EXPECT_CALL(store_, GetString(id, WiFiService::kStorageType, _))
373         .WillOnce(Return(has_type));
374     if (!has_type) {
375       EXPECT_CALL(store_, SetString(id, WiFiService::kStorageType,
376                                     kTypeWifi));
377     }
378     EXPECT_CALL(store_, GetString(id, WiFiService::kStorageMode, _))
379         .WillOnce(Return(has_mode));
380     if (!has_mode) {
381       EXPECT_CALL(store_, SetString(id, WiFiService::kStorageMode,
382                                     kModeManaged));
383     }
384     EXPECT_CALL(store_, GetString(id, WiFiService::kStorageSecurity, _))
385         .WillOnce(Return(has_security));
386     if (!has_security) {
387       EXPECT_CALL(store_, SetString(id, WiFiService::kStorageSecurity,
388                                     kSecurityWpa));
389     }
390     EXPECT_CALL(store_, GetString(id, WiFiService::kStorageSecurityClass, _))
391         .WillOnce(Return(has_security_class));
392     if (!has_security_class) {
393       EXPECT_CALL(store_, SetString(id, WiFiService::kStorageSecurityClass,
394                                     kSecurityPsk));
395     }
396   }
397 
FixupServiceEntries()398   bool FixupServiceEntries() {
399     EXPECT_CALL(store_, GetGroups()).WillOnce(Return(groups_));
400     return WiFiService::FixupServiceEntries(&store_);
401   }
402 
403  private:
404   StrictMock<MockStore> store_;
405   set<string> groups_;
406 };
407 
TEST_F(WiFiServiceTest,Constructor)408 TEST_F(WiFiServiceTest, Constructor) {
409   string histogram = metrics()->GetFullMetricName(
410       Metrics::kMetricTimeToJoinMillisecondsSuffix, Technology::kWifi);
411   EXPECT_CALL(*metrics(), AddServiceStateTransitionTimer(_, _, _, _))
412       .Times(AnyNumber());
413   EXPECT_CALL(*metrics(), AddServiceStateTransitionTimer(
414       _, histogram, Service::kStateAssociating, Service::kStateConfiguring));
415   MakeSimpleService(kSecurityNone);
416 }
417 
TEST_F(WiFiServiceTest,StorageId)418 TEST_F(WiFiServiceTest, StorageId) {
419   WiFiServiceRefPtr wifi_service = MakeSimpleService(kSecurityNone);
420   string id = wifi_service->GetStorageIdentifier();
421   for (uint i = 0; i < id.length(); ++i) {
422     EXPECT_TRUE(id[i] == '_' ||
423                 isxdigit(id[i]) ||
424                 (isalpha(id[i]) && islower(id[i])));
425   }
426   size_t mac_pos = id.find(base::ToLowerASCII(GetAnyDeviceAddress()));
427   EXPECT_NE(mac_pos, string::npos);
428   EXPECT_NE(id.find(string(kModeManaged), mac_pos), string::npos);
429 }
430 
431 // Make sure the passphrase is registered as a write only property
432 // by reading and comparing all string properties returned on the store.
TEST_F(WiFiServiceTest,PassphraseWriteOnly)433 TEST_F(WiFiServiceTest, PassphraseWriteOnly) {
434   WiFiServiceRefPtr wifi_service = MakeSimpleService(kSecurityWpa);
435   ReadablePropertyConstIterator<string> it =
436       (wifi_service->store()).GetStringPropertiesIter();
437   for ( ; !it.AtEnd(); it.Advance())
438     EXPECT_NE(it.Key(), kPassphraseProperty);
439 }
440 
441 // Make sure setting the passphrase via D-Bus Service.SetProperty validates
442 // the passphrase.
TEST_F(WiFiServiceTest,PassphraseSetPropertyValidation)443 TEST_F(WiFiServiceTest, PassphraseSetPropertyValidation) {
444   // We only spot check two password cases here to make sure the
445   // SetProperty code path does validation.  We're not going to exhaustively
446   // test for all types of passwords.
447   WiFiServiceRefPtr wifi_service = MakeSimpleService(kSecurityWep);
448   Error error;
449   EXPECT_TRUE(wifi_service->mutable_store()->SetStringProperty(
450                   kPassphraseProperty, "0:abcde", &error));
451   EXPECT_FALSE(wifi_service->mutable_store()->SetStringProperty(
452                    kPassphraseProperty, "invalid", &error));
453   EXPECT_EQ(Error::kInvalidPassphrase, error.type());
454 }
455 
TEST_F(WiFiServiceTest,PassphraseSetPropertyOpenNetwork)456 TEST_F(WiFiServiceTest, PassphraseSetPropertyOpenNetwork) {
457   WiFiServiceRefPtr wifi_service = MakeSimpleService(kSecurityNone);
458   Error error;
459   EXPECT_FALSE(wifi_service->mutable_store()->SetStringProperty(
460                    kPassphraseProperty, "invalid", &error));
461   EXPECT_EQ(Error::kNotSupported, error.type());
462 }
463 
TEST_F(WiFiServiceTest,NonUTF8SSID)464 TEST_F(WiFiServiceTest, NonUTF8SSID) {
465   vector<uint8_t> ssid;
466 
467   ssid.push_back(0xff);  // not a valid UTF-8 byte-sequence
468   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
469                                                    dispatcher(),
470                                                    metrics(),
471                                                    manager(),
472                                                    provider(),
473                                                    ssid,
474                                                    kModeManaged,
475                                                    kSecurityNone,
476                                                    false);
477   brillo::VariantDictionary properties;
478   // if service doesn't propertly sanitize SSID, this will generate SIGABRT.
479   EXPECT_TRUE(wifi_service->store().GetProperties(&properties, nullptr));
480 }
481 
482 MATCHER(PSKSecurityArgs, "") {
483   return arg.ContainsString(WPASupplicant::kPropertySecurityProtocol) &&
484       arg.GetString(WPASupplicant::kPropertySecurityProtocol) ==
485           string("WPA RSN") &&
486       arg.ContainsString(WPASupplicant::kPropertyPreSharedKey);
487 }
488 
489 MATCHER_P(FrequencyArg, has_arg, "") {
490   return has_arg ==
491       arg.ContainsInt(WPASupplicant::kNetworkPropertyFrequency);
492 }
493 
TEST_F(WiFiServiceTest,ConnectReportBSSes)494 TEST_F(WiFiServiceTest, ConnectReportBSSes) {
495   WiFiEndpointRefPtr endpoint1 =
496       MakeOpenEndpoint("a", "00:00:00:00:00:01", 0, 0);
497   WiFiEndpointRefPtr endpoint2 =
498       MakeOpenEndpoint("a", "00:00:00:00:00:02", 0, 0);
499   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityNone);
500   wifi_service->AddEndpoint(endpoint1);
501   wifi_service->AddEndpoint(endpoint2);
502   EXPECT_CALL(*metrics(), NotifyWifiAvailableBSSes(2));
503   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
504   wifi_service->Connect(nullptr, "in test");
505 }
506 
TEST_F(WiFiServiceTest,ConnectWithPreferredDevice)507 TEST_F(WiFiServiceTest, ConnectWithPreferredDevice) {
508   // Setup service, device, and endpoints.
509   WiFiServiceRefPtr wifi_service = MakeServiceWithMockManager();
510   const string kDeviceName1 = "test_device1";
511   const string kDeviceName2 = "test_device2";
512   scoped_refptr<MockWiFi> wifi1 = MakeSimpleWiFi(kDeviceName1);
513   scoped_refptr<MockWiFi> wifi2 = MakeSimpleWiFi(kDeviceName2);
514   WiFiEndpointRefPtr endpoint1 =
515       MakeOpenEndpointWithWiFi(wifi1, "a", "00:00:00:00:00:01", 0, 0);
516   WiFiEndpointRefPtr endpoint2 =
517       MakeOpenEndpointWithWiFi(wifi2, "a", "00:00:00:00:00:01", 0, 0);
518 
519   wifi_service->SetPreferredDevice(kDeviceName1, nullptr);
520   wifi_service->AddEndpoint(endpoint1);
521   wifi_service->AddEndpoint(endpoint2);
522   EXPECT_EQ(wifi1, wifi_service->wifi_);
523 
524   EXPECT_CALL(*wifi1, ConnectTo(wifi_service.get()));
525   EXPECT_CALL(*wifi2, ConnectTo(_)).Times(0);
526   wifi_service->Connect(nullptr, "in test");
527 }
528 
TEST_F(WiFiServiceTest,ConnectTaskWPA)529 TEST_F(WiFiServiceTest, ConnectTaskWPA) {
530   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityWpa);
531   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
532   Error error;
533   wifi_service->SetPassphrase("0:mumblemumblem", &error);
534   wifi_service->Connect(nullptr, "in test");
535   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
536               PSKSecurityArgs());
537 }
538 
TEST_F(WiFiServiceTest,ConnectTaskRSN)539 TEST_F(WiFiServiceTest, ConnectTaskRSN) {
540   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityRsn);
541   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
542   Error error;
543   wifi_service->SetPassphrase("0:mumblemumblem", &error);
544   wifi_service->Connect(nullptr, "in test");
545   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
546               PSKSecurityArgs());
547 }
548 
TEST_F(WiFiServiceTest,ConnectConditions)549 TEST_F(WiFiServiceTest, ConnectConditions) {
550   Error error;
551   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityNone);
552   scoped_refptr<MockProfile> mock_profile(
553       new NiceMock<MockProfile>(control_interface(), metrics(), manager()));
554   wifi_service->set_profile(mock_profile);
555   // With nothing else going on, the service should attempt to connect.
556   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
557   wifi_service->Connect(&error, "in test");
558   Mock::VerifyAndClearExpectations(wifi().get());
559 
560   // But if we're already "connecting" or "connected" then we shouldn't attempt
561   // again.
562   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get())).Times(0);
563   wifi_service->SetState(Service::kStateAssociating);
564   wifi_service->Connect(&error, "in test");
565   wifi_service->SetState(Service::kStateConfiguring);
566   wifi_service->Connect(&error, "in test");
567   wifi_service->SetState(Service::kStateConnected);
568   wifi_service->Connect(&error, "in test");
569   wifi_service->SetState(Service::kStatePortal);
570   wifi_service->Connect(&error, "in test");
571   wifi_service->SetState(Service::kStateOnline);
572   wifi_service->Connect(&error, "in test");
573   Mock::VerifyAndClearExpectations(wifi().get());
574 }
575 
TEST_F(WiFiServiceTest,ConnectTaskPSK)576 TEST_F(WiFiServiceTest, ConnectTaskPSK) {
577   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityPsk);
578   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
579   Error error;
580   wifi_service->SetPassphrase("0:mumblemumblem", &error);
581   wifi_service->Connect(nullptr, "in test");
582   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
583               PSKSecurityArgs());
584 }
585 
TEST_F(WiFiServiceTest,ConnectTask8021x)586 TEST_F(WiFiServiceTest, ConnectTask8021x) {
587   WiFiServiceRefPtr service = MakeServiceWithWiFi(kSecurity8021x);
588   service->mutable_eap()->set_identity("identity");
589   service->mutable_eap()->set_password("mumble");
590   service->OnEapCredentialsChanged(Service::kReasonCredentialsLoaded);
591   EXPECT_CALL(*wifi(), ConnectTo(service.get()));
592   service->Connect(nullptr, "in test");
593   KeyValueStore params = service->GetSupplicantConfigurationParameters();
594   EXPECT_TRUE(
595       params.ContainsString(WPASupplicant::kNetworkPropertyEapIdentity));
596   EXPECT_TRUE(params.ContainsString(WPASupplicant::kNetworkPropertyCaPath));
597 }
598 
TEST_F(WiFiServiceTest,ConnectTask8021xWithMockEap)599 TEST_F(WiFiServiceTest, ConnectTask8021xWithMockEap) {
600   WiFiServiceRefPtr service = MakeServiceWithWiFi(kSecurity8021x);
601   MockEapCredentials* eap = SetMockEap(service);
602   EXPECT_CALL(*eap, IsConnectable()).WillOnce(Return(true));
603   EXPECT_CALL(*wifi(), ConnectTo(service.get()));
604   service->OnEapCredentialsChanged(Service::kReasonCredentialsLoaded);
605   service->Connect(nullptr, "in test");
606 
607   EXPECT_CALL(*eap, PopulateSupplicantProperties(_, _));
608   // The mocked function does not actually set EAP parameters so we cannot
609   // expect them to be set.
610   service->GetSupplicantConfigurationParameters();
611 }
612 
TEST_F(WiFiServiceTest,ConnectTaskAdHocFrequency)613 TEST_F(WiFiServiceTest, ConnectTaskAdHocFrequency) {
614   vector<uint8_t> ssid(1, 'a');
615   WiFiEndpointRefPtr endpoint_nofreq =
616       MakeOpenEndpoint("a", "00:00:00:00:00:01", 0, 0);
617   WiFiEndpointRefPtr endpoint_freq =
618       MakeOpenEndpoint("a", "00:00:00:00:00:02", 2412, 0);
619 
620   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityNone);
621   wifi_service->AddEndpoint(endpoint_freq);
622   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
623   wifi_service->Connect(nullptr, "in test");
624 
625   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
626               FrequencyArg(false));
627 
628   wifi_service = new WiFiService(control_interface(),
629                                  dispatcher(),
630                                  metrics(),
631                                  manager(),
632                                  provider(),
633                                  ssid,
634                                  kModeAdhoc,
635                                  kSecurityNone,
636                                  false);
637   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
638   SetWiFiForService(wifi_service, wifi());
639   wifi_service->Connect(nullptr, "in test");
640 
641   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
642               FrequencyArg(false));
643 
644   wifi_service = new WiFiService(control_interface(),
645                                  dispatcher(),
646                                  metrics(),
647                                  manager(),
648                                  provider(),
649                                  ssid,
650                                  kModeAdhoc,
651                                  kSecurityNone,
652                                  false);
653   wifi_service->AddEndpoint(endpoint_nofreq);
654   SetWiFiForService(wifi_service, wifi());
655   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
656   wifi_service->Connect(nullptr, "in test");
657 
658   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
659               FrequencyArg(false));
660 
661   wifi_service = new WiFiService(control_interface(),
662                                  dispatcher(),
663                                  metrics(),
664                                  manager(),
665                                  provider(),
666                                  ssid,
667                                  kModeAdhoc,
668                                  kSecurityNone,
669                                  false);
670   wifi_service->AddEndpoint(endpoint_freq);
671   SetWiFiForService(wifi_service, wifi());
672   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
673   wifi_service->Connect(nullptr, "in test");
674   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
675               FrequencyArg(true));
676 }
677 
TEST_F(WiFiServiceTest,ConnectTaskWPA80211w)678 TEST_F(WiFiServiceTest, ConnectTaskWPA80211w) {
679   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityPsk);
680   WiFiEndpointRefPtr endpoint =
681       MakeOpenEndpoint("a", "00:00:00:00:00:01", 0, 0);
682   endpoint->ieee80211w_required_ = true;
683   wifi_service->AddEndpoint(endpoint);
684   Error error;
685   wifi_service->SetPassphrase("0:mumblemumblem", &error);
686   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
687   wifi_service->Connect(nullptr, "in test");
688 
689   KeyValueStore params =
690       wifi_service->GetSupplicantConfigurationParameters();
691   EXPECT_TRUE(params.ContainsString(WPASupplicant::kPropertySecurityProtocol));
692   EXPECT_TRUE(params.ContainsString(WPASupplicant::kPropertyPreSharedKey));
693   EXPECT_TRUE(params.ContainsUint(WPASupplicant::kNetworkPropertyIeee80211w));
694 }
695 
696 MATCHER_P(WEPSecurityArgsKeyIndex, index, "") {
697   uint32_t index_u32 = index;
698   return arg.ContainsString(WPASupplicant::kPropertyAuthAlg) &&
699       arg.ContainsUint8s(
700                   WPASupplicant::kPropertyWEPKey + base::IntToString(index)) &&
701       arg.ContainsUint(WPASupplicant::kPropertyWEPTxKeyIndex) &&
702       (arg.GetUint(WPASupplicant::kPropertyWEPTxKeyIndex) == index_u32);
703 }
704 
TEST_F(WiFiServiceTest,ConnectTaskWEP)705 TEST_F(WiFiServiceTest, ConnectTaskWEP) {
706   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityWep);
707   Error error;
708   wifi_service->SetPassphrase("0:abcdefghijklm", &error);
709   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
710   wifi_service->Connect(nullptr, "in test");
711   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
712               WEPSecurityArgsKeyIndex(0));
713 
714   wifi_service->SetPassphrase("abcdefghijklm", &error);
715   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
716   wifi_service->Connect(nullptr, "in test");
717   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
718               WEPSecurityArgsKeyIndex(0));
719 
720   wifi_service->SetPassphrase("1:abcdefghijklm", &error);
721   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
722   wifi_service->Connect(nullptr, "in test");
723   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
724               WEPSecurityArgsKeyIndex(1));
725 
726   wifi_service->SetPassphrase("2:abcdefghijklm", &error);
727   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
728   wifi_service->Connect(nullptr, "in test");
729   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
730               WEPSecurityArgsKeyIndex(2));
731 
732   wifi_service->SetPassphrase("3:abcdefghijklm", &error);
733   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
734   wifi_service->Connect(nullptr, "in test");
735   EXPECT_THAT(wifi_service->GetSupplicantConfigurationParameters(),
736               WEPSecurityArgsKeyIndex(3));
737 }
738 
739 // Dynamic WEP + 802.1x.
TEST_F(WiFiServiceTest,ConnectTaskDynamicWEP)740 TEST_F(WiFiServiceTest, ConnectTaskDynamicWEP) {
741   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityWep);
742 
743   wifi_service->mutable_eap()->SetKeyManagement("IEEE8021X", nullptr);
744   wifi_service->mutable_eap()->set_identity("something");
745   wifi_service->mutable_eap()->set_password("mumble");
746   wifi_service->OnEapCredentialsChanged(Service::kReasonCredentialsLoaded);
747   EXPECT_CALL(*wifi(), ConnectTo(wifi_service.get()));
748   wifi_service->Connect(nullptr, "in test");
749   KeyValueStore params =
750       wifi_service->GetSupplicantConfigurationParameters();
751   EXPECT_TRUE(
752       params.ContainsString(WPASupplicant::kNetworkPropertyEapIdentity));
753   EXPECT_TRUE(params.ContainsString(WPASupplicant::kNetworkPropertyCaPath));
754   EXPECT_FALSE(
755       params.ContainsString(WPASupplicant::kPropertySecurityProtocol));
756 }
757 
TEST_F(WiFiServiceTest,SetPassphraseResetHasEverConnected)758 TEST_F(WiFiServiceTest, SetPassphraseResetHasEverConnected) {
759   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityRsn);
760   const string kPassphrase = "abcdefgh";
761 
762   Error error;
763   // A changed passphrase should reset has_ever_connected_ field.
764   wifi_service->has_ever_connected_ = true;
765   EXPECT_TRUE(wifi_service->has_ever_connected());
766   wifi_service->SetPassphrase(kPassphrase, &error);
767   EXPECT_FALSE(wifi_service->has_ever_connected());
768 }
769 
TEST_F(WiFiServiceTest,SetPassphraseRemovesCachedCredentials)770 TEST_F(WiFiServiceTest, SetPassphraseRemovesCachedCredentials) {
771   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityRsn);
772 
773   const string kPassphrase = "abcdefgh";
774 
775   {
776     Error error;
777     // A changed passphrase should trigger cache removal.
778     EXPECT_CALL(*wifi(), ClearCachedCredentials(wifi_service.get()));
779     wifi_service->SetPassphrase(kPassphrase, &error);
780     Mock::VerifyAndClearExpectations(wifi().get());
781     EXPECT_TRUE(error.IsSuccess());
782   }
783 
784   {
785     Error error;
786     // An unchanged passphrase should not trigger cache removal.
787     EXPECT_CALL(*wifi(), ClearCachedCredentials(_)).Times(0);
788     wifi_service->SetPassphrase(kPassphrase, &error);
789     Mock::VerifyAndClearExpectations(wifi().get());
790     EXPECT_TRUE(error.IsSuccess());
791   }
792 
793   {
794     Error error;
795     // A modified passphrase should trigger cache removal.
796     EXPECT_CALL(*wifi(), ClearCachedCredentials(wifi_service.get()));
797     wifi_service->SetPassphrase(kPassphrase + "X", &error);
798     Mock::VerifyAndClearExpectations(wifi().get());
799     EXPECT_TRUE(error.IsSuccess());
800   }
801 
802   {
803     Error error;
804     // A cleared passphrase should also trigger cache removal.
805     EXPECT_CALL(*wifi(), ClearCachedCredentials(wifi_service.get()));
806     wifi_service->ClearPassphrase(&error);
807     Mock::VerifyAndClearExpectations(wifi().get());
808     EXPECT_TRUE(error.IsSuccess());
809   }
810 
811   {
812     Error error;
813     // An invalid passphrase should not trigger cache removal.
814     EXPECT_CALL(*wifi(), ClearCachedCredentials(_)).Times(0);
815     wifi_service->SetPassphrase("", &error);
816     Mock::VerifyAndClearExpectations(wifi().get());
817     EXPECT_FALSE(error.IsSuccess());
818   }
819 
820   {
821     // A change to EAP parameters in a PSK (non 802.1x) service will not
822     // trigger cache removal.
823     wifi_service->has_ever_connected_ = true;
824     EXPECT_TRUE(wifi_service->has_ever_connected());
825     EXPECT_CALL(*wifi(), ClearCachedCredentials(wifi_service.get())).Times(0);
826     wifi_service->OnEapCredentialsChanged(Service::kReasonPropertyUpdate);
827     EXPECT_TRUE(wifi_service->has_ever_connected());
828     Mock::VerifyAndClearExpectations(wifi().get());
829   }
830 
831   WiFiServiceRefPtr eap_wifi_service = MakeServiceWithWiFi(kSecurity8021x);
832 
833   {
834     // Any change to EAP parameters (including a null one) will trigger cache
835     // removal in an 802.1x service.  This is a lot less granular than the
836     // passphrase checks above.
837     // Changes in EAP parameters should also clear has_ever_connected_.
838     eap_wifi_service->has_ever_connected_ = true;
839     EXPECT_TRUE(eap_wifi_service->has_ever_connected());
840     EXPECT_CALL(*wifi(), ClearCachedCredentials(eap_wifi_service.get()));
841     eap_wifi_service->OnEapCredentialsChanged(Service::kReasonPropertyUpdate);
842     EXPECT_FALSE(eap_wifi_service->has_ever_connected());
843     Mock::VerifyAndClearExpectations(wifi().get());
844   }
845 }
846 
847 // This test is somewhat redundant, since:
848 //
849 // a) we test that generic property setters return false on a null
850 //    change (e.g. in PropertyAccessorTest.SignedIntCorrectness)
851 // b) we test that custom EAP property setters return false on a null
852 //    change in EapCredentialsTest.CustomSetterNoopChange
853 // c) we test that the various custom accessors pass through the
854 //    return value of custom setters
855 //    (e.g. PropertyAccessorTest.CustomAccessorCorrectness)
856 // d) we test that PropertyStore skips the change callback when a
857 //    property setter return false (PropertyStoreTypedTest.SetProperty)
858 //
859 // Nonetheless, I think it's worth testing the WiFi+EAP case directly.
TEST_F(WiFiServiceTest,EapAuthPropertyChangeClearsCachedCredentials)860 TEST_F(WiFiServiceTest, EapAuthPropertyChangeClearsCachedCredentials) {
861   WiFiServiceRefPtr wifi_service =
862       MakeServiceWithWiFi(kSecurity8021x);
863   PropertyStore& property_store(*wifi_service->mutable_store());
864 
865   // Property with custom accessor.
866   const string kPassword = "abcdefgh";
867   {
868     Error error;
869     // A changed passphrase should trigger cache removal.
870     EXPECT_CALL(*wifi(), ClearCachedCredentials(wifi_service.get()));
871     EXPECT_TRUE(property_store.SetStringProperty(
872         kEapPasswordProperty, kPassword, &error));
873     Mock::VerifyAndClearExpectations(wifi().get());
874     EXPECT_TRUE(error.IsSuccess());
875   }
876   {
877     Error error;
878     // An unchanged passphrase should not trigger cache removal.
879     EXPECT_CALL(*wifi(), ClearCachedCredentials(_)).Times(0);
880     EXPECT_FALSE(property_store.SetStringProperty(
881         kEapPasswordProperty, kPassword, &error));
882     Mock::VerifyAndClearExpectations(wifi().get());
883     EXPECT_TRUE(error.IsSuccess());
884   }
885   {
886     Error error;
887     // A modified passphrase should trigger cache removal.
888     EXPECT_CALL(*wifi(), ClearCachedCredentials(wifi_service.get()));
889     EXPECT_TRUE(property_store.SetStringProperty(
890         kEapPasswordProperty, kPassword + "X", &error));
891     Mock::VerifyAndClearExpectations(wifi().get());
892     EXPECT_TRUE(error.IsSuccess());
893   }
894 
895   // Property with generic accessor.
896   const string kCertId = "abcdefgh";
897   {
898     Error error;
899     // A changed cert id should trigger cache removal.
900     EXPECT_CALL(*wifi(), ClearCachedCredentials(wifi_service.get()));
901     EXPECT_TRUE(property_store.SetStringProperty(
902         kEapCertIdProperty, kCertId, &error));
903     Mock::VerifyAndClearExpectations(wifi().get());
904     EXPECT_TRUE(error.IsSuccess());
905   }
906   {
907     Error error;
908     // An unchanged cert id should not trigger cache removal.
909     EXPECT_CALL(*wifi(), ClearCachedCredentials(_)).Times(0);
910     EXPECT_FALSE(property_store.SetStringProperty(
911         kEapCertIdProperty, kCertId, &error));
912     Mock::VerifyAndClearExpectations(wifi().get());
913     EXPECT_TRUE(error.IsSuccess());
914   }
915   {
916     Error error;
917     // A modified cert id should trigger cache removal.
918     EXPECT_CALL(*wifi(), ClearCachedCredentials(wifi_service.get()));
919     EXPECT_TRUE(property_store.SetStringProperty(
920         kEapCertIdProperty, kCertId + "X", &error));
921     Mock::VerifyAndClearExpectations(wifi().get());
922     EXPECT_TRUE(error.IsSuccess());
923   }
924 }
925 
TEST_F(WiFiServiceTest,LoadHidden)926 TEST_F(WiFiServiceTest, LoadHidden) {
927   WiFiServiceRefPtr service = MakeSimpleService(kSecurityNone);
928   ASSERT_FALSE(service->hidden_ssid_);
929   NiceMock<MockStore> mock_store;
930   const string storage_id = service->GetStorageIdentifier();
931   set<string> groups;
932   groups.insert(storage_id);
933   EXPECT_CALL(mock_store, ContainsGroup(StrEq(storage_id)))
934       .WillRepeatedly(Return(true));
935   EXPECT_CALL(mock_store, GetGroupsWithProperties(
936       ContainsWiFiProperties(
937           simple_ssid(), kModeManaged, kSecurityNone)))
938       .WillRepeatedly(Return(groups));
939   EXPECT_CALL(mock_store, GetBool(_, _, _))
940       .WillRepeatedly(Return(false));
941   EXPECT_CALL(mock_store,
942               GetBool(StrEq(storage_id), WiFiService::kStorageHiddenSSID, _))
943       .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
944   EXPECT_TRUE(service->Load(&mock_store));
945   EXPECT_TRUE(service->hidden_ssid_);
946 }
947 
TEST_F(WiFiServiceTest,SetPassphraseForNonPassphraseService)948 TEST_F(WiFiServiceTest, SetPassphraseForNonPassphraseService) {
949   WiFiServiceRefPtr service = MakeSimpleService(kSecurityNone);
950   NiceMock<MockStore> mock_store;
951   const string storage_id = service->GetStorageIdentifier();
952   set<string> groups;
953   groups.insert(storage_id);
954   EXPECT_CALL(mock_store, ContainsGroup(StrEq(storage_id)))
955       .WillRepeatedly(Return(true));
956   EXPECT_CALL(mock_store, GetGroupsWithProperties(
957       ContainsWiFiProperties(
958           simple_ssid(), kModeManaged, kSecurityNone)))
959       .WillRepeatedly(Return(groups));
960 
961   EXPECT_TRUE(service->Load(&mock_store));
962   Error error;
963   EXPECT_FALSE(service->SetPassphrase("password", &error));
964   EXPECT_TRUE(error.type() == Error::kNotSupported);
965 }
966 
TEST_F(WiFiServiceTest,LoadMultipleMatchingGroups)967 TEST_F(WiFiServiceTest, LoadMultipleMatchingGroups) {
968   WiFiServiceRefPtr service = MakeServiceWithWiFi(kSecurityNone);
969   set<string> groups;
970   groups.insert("id0");
971   groups.insert("id1");
972   // Make sure we retain the first matched group in the same way that
973   // WiFiService::Load() will.
974   string first_group = *groups.begin();
975 
976   NiceMock<MockStore> mock_store;
977   EXPECT_CALL(mock_store, GetGroupsWithProperties(
978       ContainsWiFiProperties(
979           simple_ssid(), kModeManaged, kSecurityNone)))
980       .WillRepeatedly(Return(groups));
981   EXPECT_CALL(mock_store, ContainsGroup(first_group))
982       .WillRepeatedly(Return(true));
983   EXPECT_CALL(mock_store, ContainsGroup(StrNe(first_group))).Times(0);
984   EXPECT_CALL(mock_store, GetBool(first_group, _, _))
985       .WillRepeatedly(Return(false));
986   EXPECT_CALL(mock_store, GetBool(StrNe(first_group), _, _)).Times(0);
987   ScopedMockLog log;
988   EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
989   EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
990                        EndsWith("choosing the first.")));
991   EXPECT_TRUE(service->Load(&mock_store));
992 }
993 
TEST_F(WiFiServiceSecurityTest,WPAMapping)994 TEST_F(WiFiServiceSecurityTest, WPAMapping) {
995   EXPECT_TRUE(TestStorageMapping(kSecurityRsn, kSecurityPsk));
996   EXPECT_TRUE(TestStorageMapping(kSecurityWpa, kSecurityPsk));
997   EXPECT_TRUE(TestStorageMapping(kSecurityPsk, kSecurityPsk));
998   EXPECT_TRUE(TestStorageMapping(kSecurityWep, kSecurityWep));
999   EXPECT_TRUE(TestStorageMapping(kSecurityNone, kSecurityNone));
1000   EXPECT_TRUE(TestStorageMapping(kSecurity8021x, kSecurity8021x));
1001 }
1002 
TEST_F(WiFiServiceSecurityTest,LoadMapping)1003 TEST_F(WiFiServiceSecurityTest, LoadMapping) {
1004   EXPECT_TRUE(TestLoadMapping(kSecurityRsn, kSecurityPsk, true));
1005   EXPECT_TRUE(TestLoadMapping(kSecurityRsn, kSecurityRsn, false));
1006   EXPECT_TRUE(TestLoadMapping(kSecurityRsn, kSecurityWpa, false));
1007   EXPECT_TRUE(TestLoadMapping(kSecurityWpa, kSecurityPsk, true));
1008   EXPECT_TRUE(TestLoadMapping(kSecurityWpa, kSecurityWpa, false));
1009   EXPECT_TRUE(TestLoadMapping(kSecurityWpa, kSecurityRsn, false));
1010   EXPECT_TRUE(TestLoadMapping(kSecurityWep, kSecurityWep, true));
1011   EXPECT_TRUE(TestLoadMapping(kSecurityWep, kSecurityPsk, false));
1012 }
1013 
TEST_F(WiFiServiceTest,LoadAndUnloadPassphrase)1014 TEST_F(WiFiServiceTest, LoadAndUnloadPassphrase) {
1015   WiFiServiceRefPtr service = MakeSimpleService(kSecurityPsk);
1016   NiceMock<MockStore> mock_store;
1017   const string kStorageId = service->GetStorageIdentifier();
1018   EXPECT_CALL(mock_store, ContainsGroup(StrEq(kStorageId)))
1019       .WillRepeatedly(Return(true));
1020   set<string> groups;
1021   groups.insert(kStorageId);
1022   EXPECT_CALL(mock_store, GetGroupsWithProperties(
1023       ContainsWiFiProperties(
1024           simple_ssid(), kModeManaged, kSecurityPsk)))
1025       .WillRepeatedly(Return(groups));
1026   EXPECT_CALL(mock_store, GetBool(_, _, _))
1027       .WillRepeatedly(Return(false));
1028   const string kPassphrase = "passphrase";
1029   EXPECT_CALL(mock_store,
1030               GetCryptedString(StrEq(kStorageId),
1031                                WiFiService::kStoragePassphrase, _))
1032       .WillRepeatedly(DoAll(SetArgumentPointee<2>(kPassphrase), Return(true)));
1033   EXPECT_CALL(mock_store,
1034               GetCryptedString(StrEq(kStorageId),
1035                                StrNe(WiFiService::kStoragePassphrase), _))
1036       .WillRepeatedly(Return(false));
1037   EXPECT_TRUE(service->need_passphrase_);
1038   EXPECT_TRUE(service->Load(&mock_store));
1039   EXPECT_EQ(kPassphrase, service->passphrase_);
1040   EXPECT_TRUE(service->connectable());
1041   EXPECT_FALSE(service->need_passphrase_);
1042   service->Unload();
1043   EXPECT_EQ(string(""), service->passphrase_);
1044   EXPECT_FALSE(service->connectable());
1045   EXPECT_TRUE(service->need_passphrase_);
1046 }
1047 
TEST_F(WiFiServiceTest,LoadPassphraseClearCredentials)1048 TEST_F(WiFiServiceTest, LoadPassphraseClearCredentials) {
1049   const string kOldPassphrase = "oldpassphrase";
1050   const string kPassphrase = "passphrase";
1051 
1052   const bool kHasEverConnected = true;
1053   WiFiServiceRefPtr service = MakeServiceWithWiFi(kSecurityPsk);
1054   NiceMock<MockStore> mock_store;
1055   const string kStorageId = service->GetStorageIdentifier();
1056   EXPECT_CALL(mock_store, ContainsGroup(StrEq(kStorageId)))
1057       .WillRepeatedly(Return(true));
1058   set<string> groups;
1059   groups.insert(kStorageId);
1060   EXPECT_CALL(mock_store, GetGroupsWithProperties(
1061       ContainsWiFiProperties(
1062           simple_ssid(), kModeManaged, kSecurityPsk)))
1063       .WillRepeatedly(Return(groups));
1064   EXPECT_CALL(mock_store, GetBool(_, _, _))
1065       .WillRepeatedly(Return(false));
1066   EXPECT_CALL(mock_store,
1067               GetCryptedString(StrEq(kStorageId),
1068                                WiFiService::kStoragePassphrase, _))
1069       .WillRepeatedly(DoAll(SetArgumentPointee<2>(kPassphrase), Return(true)));
1070   EXPECT_CALL(mock_store,
1071               GetCryptedString(StrEq(kStorageId),
1072                                StrNe(WiFiService::kStoragePassphrase), _))
1073       .WillRepeatedly(Return(false));
1074   EXPECT_CALL(mock_store,
1075               GetBool(kStorageId, Service::kStorageHasEverConnected, _))
1076       .WillRepeatedly(DoAll(SetArgumentPointee<2>(kHasEverConnected),
1077                             Return(true)));
1078   // Set old passphrase for service
1079   EXPECT_TRUE(service->need_passphrase_);
1080   service->passphrase_ = kOldPassphrase;
1081   service->has_ever_connected_ = true;
1082 
1083   scoped_refptr<MockProfile> mock_profile(
1084       new NiceMock<MockProfile>(control_interface(), metrics(), manager()));
1085   service->set_profile(mock_profile);
1086   // Detect if the service is going to attempt to update the stored profile.
1087   EXPECT_CALL(*mock_profile, GetConstStorage()).Times(0);
1088 
1089   // The kOldPassphrase is different than the newly loaded passhprase,
1090   // so the credentials should be cleared.
1091   EXPECT_CALL(*wifi(), ClearCachedCredentials(_)).Times(1);
1092   EXPECT_CALL(*mock_profile, UpdateService(_)).Times(0);
1093   EXPECT_TRUE(service->Load(&mock_store));
1094   EXPECT_EQ(kPassphrase, service->passphrase_);
1095   EXPECT_TRUE(service->has_ever_connected_);
1096 
1097   Mock::VerifyAndClearExpectations(wifi().get());
1098   Mock::VerifyAndClearExpectations(mock_profile.get());
1099 
1100 
1101   // Repeat Service::Load with same old and new passphrase. Since the old
1102   // and new passphrase match, verify the cache is not cleared during
1103   // profile load.
1104   service->set_profile(mock_profile);
1105   EXPECT_CALL(*mock_profile, GetConstStorage()).Times(0);
1106   EXPECT_CALL(*wifi(), ClearCachedCredentials(_)).Times(0);
1107   EXPECT_TRUE(service->Load(&mock_store));
1108   EXPECT_EQ(kPassphrase, service->passphrase_);
1109   EXPECT_TRUE(service->has_ever_connected_);
1110 }
1111 
TEST_F(WiFiServiceTest,ConfigureMakesConnectable)1112 TEST_F(WiFiServiceTest, ConfigureMakesConnectable) {
1113   string guid("legit_guid");
1114   KeyValueStore args;
1115   args.SetString(kEapIdentityProperty, "legit_identity");
1116   args.SetString(kEapPasswordProperty, "legit_password");
1117   args.SetString(kEapMethodProperty, "PEAP");
1118   args.SetString(kGuidProperty, guid);
1119   Error error;
1120 
1121   WiFiServiceRefPtr service = MakeSimpleService(kSecurity8021x);
1122   // Hack the GUID in so that we don't have to mess about with WiFi to regsiter
1123   // our service.  This way, Manager will handle the lookup itself.
1124   service->SetGuid(guid, nullptr);
1125   manager()->RegisterService(service);
1126   EXPECT_FALSE(service->connectable());
1127   EXPECT_EQ(service.get(), manager()->GetService(args, &error).get());
1128   EXPECT_TRUE(error.IsSuccess());
1129   EXPECT_TRUE(service->connectable());
1130 }
1131 
TEST_F(WiFiServiceTest,ConfigurePassphrase)1132 TEST_F(WiFiServiceTest, ConfigurePassphrase) {
1133   EXPECT_EQ(Error::kNotSupported,
1134             TestConfigurePassphrase(kSecurityNone, ""));
1135   EXPECT_EQ(Error::kNotSupported,
1136             TestConfigurePassphrase(kSecurityNone, "foo"));
1137   EXPECT_EQ(Error::kSuccess,
1138             TestConfigurePassphrase(kSecurityWep, nullptr));
1139   EXPECT_EQ(Error::kInvalidPassphrase,
1140             TestConfigurePassphrase(kSecurityWep, ""));
1141   EXPECT_EQ(Error::kInvalidPassphrase,
1142             TestConfigurePassphrase(kSecurityWep, "abcd"));
1143   EXPECT_EQ(Error::kSuccess,
1144             TestConfigurePassphrase(kSecurityWep, "abcde"));
1145   EXPECT_EQ(Error::kSuccess,
1146             TestConfigurePassphrase(kSecurityWep, "abcdefghijklm"));
1147   EXPECT_EQ(Error::kSuccess,
1148             TestConfigurePassphrase(kSecurityWep, "0:abcdefghijklm"));
1149   EXPECT_EQ(Error::kSuccess,
1150             TestConfigurePassphrase(kSecurityWep, "0102030405"));
1151   EXPECT_EQ(Error::kInvalidPassphrase,
1152             TestConfigurePassphrase(kSecurityWep, "0x0102030405"));
1153   EXPECT_EQ(Error::kInvalidPassphrase,
1154             TestConfigurePassphrase(kSecurityWep, "O102030405"));
1155   EXPECT_EQ(Error::kInvalidPassphrase,
1156             TestConfigurePassphrase(kSecurityWep, "1:O102030405"));
1157   EXPECT_EQ(Error::kInvalidPassphrase,
1158             TestConfigurePassphrase(kSecurityWep, "1:0xO102030405"));
1159   EXPECT_EQ(Error::kInvalidPassphrase,
1160             TestConfigurePassphrase(kSecurityWep, "0xO102030405"));
1161   EXPECT_EQ(Error::kSuccess,
1162             TestConfigurePassphrase(kSecurityWep,
1163                                     "0102030405060708090a0b0c0d"));
1164   EXPECT_EQ(Error::kSuccess,
1165             TestConfigurePassphrase(kSecurityWep,
1166                                     "0102030405060708090A0B0C0D"));
1167   EXPECT_EQ(Error::kSuccess,
1168             TestConfigurePassphrase(kSecurityWep,
1169                                     "0:0102030405060708090a0b0c0d"));
1170   EXPECT_EQ(Error::kSuccess,
1171             TestConfigurePassphrase(kSecurityWep,
1172                                     "0:0x0102030405060708090a0b0c0d"));
1173   EXPECT_EQ(Error::kSuccess,
1174             TestConfigurePassphrase(kSecurityWpa, nullptr));
1175   EXPECT_EQ(Error::kSuccess,
1176             TestConfigurePassphrase(kSecurityWpa, "secure password"));
1177   EXPECT_EQ(Error::kInvalidPassphrase,
1178             TestConfigurePassphrase(kSecurityWpa, ""));
1179   EXPECT_EQ(Error::kSuccess, TestConfigurePassphrase(
1180       kSecurityWpa,
1181       string(IEEE_80211::kWPAAsciiMinLen, 'Z').c_str()));
1182   EXPECT_EQ(Error::kSuccess, TestConfigurePassphrase(
1183       kSecurityWpa,
1184       string(IEEE_80211::kWPAAsciiMaxLen, 'Z').c_str()));
1185   // subtle: invalid length for hex key, but valid as ascii passphrase
1186   EXPECT_EQ(Error::kSuccess, TestConfigurePassphrase(
1187       kSecurityWpa,
1188       string(IEEE_80211::kWPAHexLen-1, '1').c_str()));
1189   EXPECT_EQ(Error::kSuccess, TestConfigurePassphrase(
1190       kSecurityWpa,
1191       string(IEEE_80211::kWPAHexLen, '1').c_str()));
1192   EXPECT_EQ(Error::kInvalidPassphrase, TestConfigurePassphrase(
1193       kSecurityWpa,
1194       string(IEEE_80211::kWPAAsciiMinLen-1, 'Z').c_str()));
1195   EXPECT_EQ(Error::kInvalidPassphrase, TestConfigurePassphrase(
1196       kSecurityWpa,
1197       string(IEEE_80211::kWPAAsciiMaxLen+1, 'Z').c_str()));
1198   EXPECT_EQ(Error::kInvalidPassphrase, TestConfigurePassphrase(
1199       kSecurityWpa,
1200       string(IEEE_80211::kWPAHexLen+1, '1').c_str()));
1201 }
1202 
TEST_F(WiFiServiceTest,ConfigureRedundantProperties)1203 TEST_F(WiFiServiceTest, ConfigureRedundantProperties) {
1204   WiFiServiceRefPtr service = MakeSimpleService(kSecurityNone);
1205   KeyValueStore args;
1206   args.SetString(kTypeProperty, kTypeWifi);
1207   args.SetString(kSSIDProperty, simple_ssid_string());
1208   args.SetString(kSecurityProperty, kSecurityNone);
1209   args.SetString(kWifiHexSsid, "This is ignored even if it is invalid hex.");
1210   const string kGUID = "aguid";
1211   args.SetString(kGuidProperty, kGUID);
1212 
1213   EXPECT_EQ("", service->guid());
1214   Error error;
1215   service->Configure(args, &error);
1216   EXPECT_TRUE(error.IsSuccess());
1217   EXPECT_EQ(kGUID, service->guid());
1218 }
1219 
TEST_F(WiFiServiceTest,DisconnectWithWiFi)1220 TEST_F(WiFiServiceTest, DisconnectWithWiFi) {
1221   WiFiServiceRefPtr service = MakeServiceWithWiFi(kSecurityWep);
1222   EXPECT_CALL(*wifi(), DisconnectFromIfActive(service.get())).Times(1);
1223   Error error;
1224   service->Disconnect(&error, "in test");
1225 }
1226 
TEST_F(WiFiServiceTest,DisconnectWithoutWiFi)1227 TEST_F(WiFiServiceTest, DisconnectWithoutWiFi) {
1228   WiFiServiceRefPtr service = MakeSimpleService(kSecurityWep);
1229   EXPECT_CALL(*wifi(), DisconnectFrom(_)).Times(0);
1230   Error error;
1231   service->Disconnect(&error, "in test");
1232   EXPECT_EQ(Error::kOperationFailed, error.type());
1233 }
1234 
TEST_F(WiFiServiceTest,DisconnectWithoutWiFiWhileAssociating)1235 TEST_F(WiFiServiceTest, DisconnectWithoutWiFiWhileAssociating) {
1236   WiFiServiceRefPtr service = MakeSimpleService(kSecurityWep);
1237   EXPECT_CALL(*wifi(), DisconnectFrom(_)).Times(0);
1238   service->SetState(Service::kStateAssociating);
1239   ScopedMockLog log;
1240   EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
1241   EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
1242                        HasSubstr("WiFi endpoints do not (yet) exist.")));
1243   Error error;
1244   service->Disconnect(&error, "in test");
1245   EXPECT_EQ(Error::kOperationFailed, error.type());
1246 }
1247 
TEST_F(WiFiServiceTest,UnloadAndClearCacheWEP)1248 TEST_F(WiFiServiceTest, UnloadAndClearCacheWEP) {
1249   WiFiServiceRefPtr service = MakeServiceWithWiFi(kSecurityWep);
1250   EXPECT_CALL(*wifi(), ClearCachedCredentials(service.get())).Times(1);
1251   EXPECT_CALL(*wifi(), DisconnectFromIfActive(service.get())).Times(1);
1252   service->Unload();
1253 }
1254 
TEST_F(WiFiServiceTest,UnloadAndClearCache8021x)1255 TEST_F(WiFiServiceTest, UnloadAndClearCache8021x) {
1256   WiFiServiceRefPtr service = MakeServiceWithWiFi(kSecurity8021x);
1257   EXPECT_CALL(*wifi(), ClearCachedCredentials(service.get())).Times(1);
1258   EXPECT_CALL(*wifi(), DisconnectFromIfActive(service.get())).Times(1);
1259   service->Unload();
1260 }
1261 
TEST_F(WiFiServiceTest,ParseStorageIdentifierNone)1262 TEST_F(WiFiServiceTest, ParseStorageIdentifierNone) {
1263   WiFiServiceRefPtr service = MakeSimpleService(kSecurityNone);
1264   const string storage_id = service->GetStorageIdentifier();
1265   string address;
1266   string mode;
1267   string security;
1268   EXPECT_TRUE(service->ParseStorageIdentifier(storage_id, &address, &mode,
1269                                               &security));
1270   EXPECT_EQ(base::ToLowerASCII(GetAnyDeviceAddress()), address);
1271   EXPECT_EQ(kModeManaged, mode);
1272   EXPECT_EQ(kSecurityNone, security);
1273 }
1274 
TEST_F(WiFiServiceTest,ParseStorageIdentifier8021x)1275 TEST_F(WiFiServiceTest, ParseStorageIdentifier8021x) {
1276   // Do a separate test for 802.1x, since kSecurity8021x contains a "_",
1277   // which needs to be dealt with specially in the parser.
1278   WiFiServiceRefPtr service = MakeSimpleService(kSecurity8021x);
1279   const string storage_id = service->GetStorageIdentifier();
1280   string address;
1281   string mode;
1282   string security;
1283   EXPECT_TRUE(service->ParseStorageIdentifier(storage_id, &address, &mode,
1284                                               &security));
1285   EXPECT_EQ(base::ToLowerASCII(GetAnyDeviceAddress()), address);
1286   EXPECT_EQ(kModeManaged, mode);
1287   EXPECT_EQ(kSecurity8021x, security);
1288 }
1289 
TEST_F(WiFiServiceFixupStorageTest,FixedEntries)1290 TEST_F(WiFiServiceFixupStorageTest, FixedEntries) {
1291   const string kNonWiFiId = "vpn_foo";
1292   const string kUnparsableWiFiId = "wifi_foo";
1293 
1294   AddGroup(kNonWiFiId);
1295   AddGroup(kUnparsableWiFiId);
1296   AddServiceEntry(true, true, true, true);
1297   AddServiceEntry(false, false, false, false);
1298   AddServiceEntry(true, true, true, true);
1299   AddServiceEntry(false, false, false, false);
1300   EXPECT_TRUE(FixupServiceEntries());
1301 }
1302 
TEST_F(WiFiServiceFixupStorageTest,NoFixedEntries)1303 TEST_F(WiFiServiceFixupStorageTest, NoFixedEntries) {
1304   const string kNonWiFiId = "vpn_foo";
1305   const string kUnparsableWiFiId = "wifi_foo";
1306 
1307   AddGroup(kNonWiFiId);
1308   AddGroup(kUnparsableWiFiId);
1309   AddServiceEntry(true, true, true, true);
1310   EXPECT_FALSE(FixupServiceEntries());
1311 }
1312 
TEST_F(WiFiServiceFixupStorageTest,MissingTypeProperty)1313 TEST_F(WiFiServiceFixupStorageTest, MissingTypeProperty) {
1314   AddServiceEntry(false, true, true, true);
1315   EXPECT_TRUE(FixupServiceEntries());
1316 }
1317 
TEST_F(WiFiServiceFixupStorageTest,MissingModeProperty)1318 TEST_F(WiFiServiceFixupStorageTest, MissingModeProperty) {
1319   AddServiceEntry(true, false, true, true);
1320   EXPECT_TRUE(FixupServiceEntries());
1321 }
1322 
TEST_F(WiFiServiceFixupStorageTest,MissingSecurityProperty)1323 TEST_F(WiFiServiceFixupStorageTest, MissingSecurityProperty) {
1324   AddServiceEntry(true, true, false, true);
1325   EXPECT_TRUE(FixupServiceEntries());
1326 }
1327 
TEST_F(WiFiServiceFixupStorageTest,MissingSecurityClassProperty)1328 TEST_F(WiFiServiceFixupStorageTest, MissingSecurityClassProperty) {
1329   AddServiceEntry(true, true, true, false);
1330   EXPECT_TRUE(FixupServiceEntries());
1331 }
1332 
TEST_F(WiFiServiceTest,Connectable)1333 TEST_F(WiFiServiceTest, Connectable) {
1334   // Open network should be connectable.
1335   EXPECT_TRUE(CheckConnectable(kSecurityNone, nullptr, false));
1336 
1337   // Open network should remain connectable if we try to set a password on it.
1338   EXPECT_TRUE(CheckConnectable(kSecurityNone, "abcde", false));
1339 
1340   // WEP network with passphrase set should be connectable.
1341   EXPECT_TRUE(CheckConnectable(kSecurityWep, "abcde", false));
1342 
1343   // WEP network without passphrase set should NOT be connectable.
1344   EXPECT_FALSE(CheckConnectable(kSecurityWep, nullptr, false));
1345 
1346   // A bad passphrase should not make a WEP network connectable.
1347   EXPECT_FALSE(CheckConnectable(kSecurityWep, "a", false));
1348 
1349   // Similar to WEP, for WPA.
1350   EXPECT_TRUE(CheckConnectable(kSecurityWpa, "abcdefgh", false));
1351   EXPECT_FALSE(CheckConnectable(kSecurityWpa, nullptr, false));
1352   EXPECT_FALSE(CheckConnectable(kSecurityWpa, "a", false));
1353 
1354   // 802.1x without connectable EAP credentials should NOT be connectable.
1355   EXPECT_FALSE(CheckConnectable(kSecurity8021x, nullptr, false));
1356 
1357   // 802.1x with connectable EAP credentials should be connectable.
1358   EXPECT_TRUE(CheckConnectable(kSecurity8021x, nullptr, true));
1359 
1360   // Dynamic WEP + 802.1X should be connectable under the same conditions.
1361   EXPECT_TRUE(CheckConnectable(kSecurityWep, nullptr, true));
1362 }
1363 
TEST_F(WiFiServiceTest,IsAutoConnectable)1364 TEST_F(WiFiServiceTest, IsAutoConnectable) {
1365   const char* reason;
1366   WiFiServiceRefPtr service = MakeSimpleService(kSecurityNone);
1367   EXPECT_CALL(*wifi(), IsIdle())
1368       .WillRepeatedly(Return(true));
1369   EXPECT_FALSE(service->HasEndpoints());
1370   EXPECT_FALSE(service->IsAutoConnectable(&reason));
1371   EXPECT_STREQ(WiFiService::kAutoConnNoEndpoint, reason);
1372 
1373   reason = "";
1374   WiFiEndpointRefPtr endpoint =
1375       MakeOpenEndpoint("a", "00:00:00:00:00:01", 0, 0);
1376   service->AddEndpoint(endpoint);
1377   EXPECT_CALL(*wifi(), IsIdle())
1378       .WillRepeatedly(Return(true));
1379   EXPECT_TRUE(service->HasEndpoints());
1380   EXPECT_TRUE(service->IsAutoConnectable(&reason));
1381   EXPECT_STREQ("", reason);
1382 
1383   // WiFi only supports connecting to one Service at a time. So, to
1384   // avoid disrupting connectivity, we only allow auto-connection to
1385   // a WiFiService when the corresponding WiFi is idle.
1386   EXPECT_CALL(*wifi(), IsIdle())
1387       .WillRepeatedly(Return(false));
1388   EXPECT_TRUE(service->HasEndpoints());
1389   EXPECT_FALSE(service->IsAutoConnectable(&reason));
1390   EXPECT_STREQ(WiFiService::kAutoConnBusy, reason);
1391 }
1392 
TEST_F(WiFiServiceTest,AutoConnect)1393 TEST_F(WiFiServiceTest, AutoConnect) {
1394   const char* reason;
1395   WiFiServiceRefPtr service = MakeSimpleService(kSecurityNone);
1396   EXPECT_FALSE(service->IsAutoConnectable(&reason));
1397   EXPECT_CALL(*wifi(), ConnectTo(_)).Times(0);
1398   service->AutoConnect();
1399   dispatcher()->DispatchPendingEvents();
1400 
1401   WiFiEndpointRefPtr endpoint =
1402       MakeOpenEndpoint("a", "00:00:00:00:00:01", 0, 0);
1403   service->AddEndpoint(endpoint);
1404   EXPECT_CALL(*wifi(), IsIdle())
1405       .WillRepeatedly(Return(true));
1406   EXPECT_TRUE(service->IsAutoConnectable(&reason));
1407   EXPECT_CALL(*wifi(), ConnectTo(_));
1408   service->AutoConnect();
1409   dispatcher()->DispatchPendingEvents();
1410 
1411   Error error;
1412   service->UserInitiatedDisconnect(&error);
1413   dispatcher()->DispatchPendingEvents();
1414   EXPECT_FALSE(service->IsAutoConnectable(&reason));
1415 }
1416 
TEST_F(WiFiServiceTest,ClearWriteOnlyDerivedProperty)1417 TEST_F(WiFiServiceTest, ClearWriteOnlyDerivedProperty) {
1418   WiFiServiceRefPtr wifi_service = MakeSimpleService(kSecurityWep);
1419 
1420   EXPECT_EQ("", wifi_service->passphrase_);
1421 
1422   Error error;
1423   const string kPassphrase = "0:abcde";
1424   EXPECT_TRUE(
1425       wifi_service->mutable_store()->SetAnyProperty(kPassphraseProperty,
1426                                                     brillo::Any(kPassphrase),
1427                                                     &error));
1428   EXPECT_EQ(kPassphrase, wifi_service->passphrase_);
1429 
1430   EXPECT_TRUE(wifi_service->mutable_store()->ClearProperty(kPassphraseProperty,
1431                                                            &error));
1432   EXPECT_EQ("", wifi_service->passphrase_);
1433 }
1434 
TEST_F(WiFiServiceTest,SignalToStrength)1435 TEST_F(WiFiServiceTest, SignalToStrength) {
1436   // Verify that our mapping is sane, in the sense that it preserves ordering.
1437   // We break the test into two domains, because we assume that positive
1438   // values aren't actually in dBm.
1439   for (int16_t i = std::numeric_limits<int16_t>::min(); i < 0; ++i) {
1440     int16_t current_mapped = WiFiService::SignalToStrength(i);
1441     int16_t next_mapped =  WiFiService::SignalToStrength(i+1);
1442     EXPECT_LE(current_mapped, next_mapped)
1443         << "(original values " << i << " " << i+1 << ")";
1444     EXPECT_GE(current_mapped, Service::kStrengthMin);
1445     EXPECT_LE(current_mapped, Service::kStrengthMax);
1446   }
1447   for (int16_t i = 1; i < std::numeric_limits<int16_t>::max(); ++i) {
1448     int16_t current_mapped = WiFiService::SignalToStrength(i);
1449     int16_t next_mapped =  WiFiService::SignalToStrength(i+1);
1450     EXPECT_LE(current_mapped, next_mapped)
1451         << "(original values " << i << " " << i+1 << ")";
1452     EXPECT_GE(current_mapped, Service::kStrengthMin);
1453     EXPECT_LE(current_mapped, Service::kStrengthMax);
1454   }
1455 }
1456 
TEST_F(WiFiServiceUpdateFromEndpointsTest,Strengths)1457 TEST_F(WiFiServiceUpdateFromEndpointsTest, Strengths) {
1458   // If the chosen signal values don't map to distinct strength
1459   // values, then we can't expect our other tests to pass. So verify
1460   // their distinctness.
1461   EXPECT_TRUE(kOkEndpointStrength != kBadEndpointStrength);
1462   EXPECT_TRUE(kOkEndpointStrength != kGoodEndpointStrength);
1463   EXPECT_TRUE(kGoodEndpointStrength != kBadEndpointStrength);
1464 }
1465 
TEST_F(WiFiServiceUpdateFromEndpointsTest,Floating)1466 TEST_F(WiFiServiceUpdateFromEndpointsTest, Floating) {
1467   // Initial endpoint updates values.
1468   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, kOkEndpointFrequency));
1469   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, kOkEndpointBssId));
1470   EXPECT_CALL(adaptor,
1471               EmitUint8Changed(kSignalStrengthProperty, kOkEndpointStrength));
1472   EXPECT_CALL(adaptor,
1473               EmitUint16Changed(kWifiPhyMode, Metrics::kWiFiNetworkPhyMode11b));
1474   service->AddEndpoint(ok_endpoint);
1475   EXPECT_EQ(1, service->GetEndpointCount());
1476   Mock::VerifyAndClearExpectations(&adaptor);
1477 
1478   // Endpoint with stronger signal updates values.
1479   EXPECT_CALL(adaptor,
1480               EmitUint16Changed(kWifiFrequency, kGoodEndpointFrequency));
1481   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, kGoodEndpointBssId));
1482   EXPECT_CALL(adaptor,
1483               EmitUint8Changed(kSignalStrengthProperty, kGoodEndpointStrength));
1484   // However, both endpoints are 11b.
1485   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiPhyMode, _)).Times(0);
1486   service->AddEndpoint(good_endpoint);
1487   EXPECT_EQ(2, service->GetEndpointCount());
1488   Mock::VerifyAndClearExpectations(&adaptor);
1489 
1490   // Endpoint with lower signal does not change values.
1491   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, _)).Times(0);
1492   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, _)).Times(0);
1493   EXPECT_CALL(adaptor,
1494               EmitUint8Changed(kSignalStrengthProperty, _)).Times(0);
1495   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiPhyMode, _)).Times(0);
1496   service->AddEndpoint(bad_endpoint);
1497   EXPECT_EQ(3, service->GetEndpointCount());
1498   Mock::VerifyAndClearExpectations(&adaptor);
1499 
1500   // Removing non-optimal endpoint does not change values.
1501   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, _)).Times(0);
1502   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, _)).Times(0);
1503   EXPECT_CALL(adaptor,
1504               EmitUint8Changed(kSignalStrengthProperty, _)).Times(0);
1505   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiPhyMode, _)).Times(0);
1506   service->RemoveEndpoint(bad_endpoint);
1507   EXPECT_EQ(2, service->GetEndpointCount());
1508   Mock::VerifyAndClearExpectations(&adaptor);
1509 
1510   // Removing optimal endpoint updates values.
1511   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, kOkEndpointFrequency));
1512   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, kOkEndpointBssId));
1513   EXPECT_CALL(adaptor,
1514               EmitUint8Changed(kSignalStrengthProperty, kOkEndpointStrength));
1515   // However, both endpoints are 11b.
1516   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiPhyMode, _)).Times(0);
1517   service->RemoveEndpoint(good_endpoint);
1518   EXPECT_EQ(1, service->GetEndpointCount());
1519   Mock::VerifyAndClearExpectations(&adaptor);
1520 
1521   // Removing last endpoint updates values (and doesn't crash).
1522   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, _));
1523   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, _));
1524   EXPECT_CALL(adaptor, EmitUint8Changed(kSignalStrengthProperty, _));
1525   EXPECT_CALL(adaptor, EmitUint16Changed(
1526       kWifiPhyMode, Metrics::kWiFiNetworkPhyModeUndef));
1527   service->RemoveEndpoint(ok_endpoint);
1528   EXPECT_EQ(0, service->GetEndpointCount());
1529   Mock::VerifyAndClearExpectations(&adaptor);
1530 }
1531 
TEST_F(WiFiServiceUpdateFromEndpointsTest,Connected)1532 TEST_F(WiFiServiceUpdateFromEndpointsTest, Connected) {
1533   EXPECT_CALL(adaptor, EmitUint16Changed(_, _)).Times(AnyNumber());
1534   EXPECT_CALL(adaptor, EmitStringChanged(_, _)).Times(AnyNumber());
1535   EXPECT_CALL(adaptor, EmitUint8Changed(_, _)).Times(AnyNumber());
1536   EXPECT_CALL(adaptor, EmitBoolChanged(_, _)).Times(AnyNumber());
1537   service->AddEndpoint(bad_endpoint);
1538   service->AddEndpoint(ok_endpoint);
1539   EXPECT_EQ(2, service->GetEndpointCount());
1540   Mock::VerifyAndClearExpectations(&adaptor);
1541 
1542   // Setting current endpoint forces adoption of its values, even if it
1543   // doesn't have the highest signal.
1544   EXPECT_CALL(adaptor,
1545               EmitUint16Changed(kWifiFrequency, kBadEndpointFrequency));
1546   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, kBadEndpointBssId));
1547   EXPECT_CALL(adaptor,
1548               EmitUint8Changed(kSignalStrengthProperty, kBadEndpointStrength));
1549   service->NotifyCurrentEndpoint(bad_endpoint);
1550   Mock::VerifyAndClearExpectations(&adaptor);
1551 
1552   // Adding a better endpoint doesn't matter, when current endpoint is set.
1553   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, _)).Times(0);
1554   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, _)).Times(0);
1555   EXPECT_CALL(adaptor,
1556               EmitUint8Changed(kSignalStrengthProperty, _)).Times(0);
1557   service->AddEndpoint(good_endpoint);
1558   EXPECT_EQ(3, service->GetEndpointCount());
1559   Mock::VerifyAndClearExpectations(&adaptor);
1560 
1561   // Removing a better endpoint doesn't matter, when current endpoint is set.
1562   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, _)).Times(0);
1563   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, _)).Times(0);
1564   EXPECT_CALL(adaptor,
1565               EmitUint8Changed(kSignalStrengthProperty, _)).Times(0);
1566   service->RemoveEndpoint(good_endpoint);
1567   Mock::VerifyAndClearExpectations(&adaptor);
1568 
1569   // Removing the current endpoint is safe and sane.
1570   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, kOkEndpointFrequency));
1571   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, kOkEndpointBssId));
1572   EXPECT_CALL(adaptor,
1573               EmitUint8Changed(kSignalStrengthProperty, kOkEndpointStrength));
1574   service->RemoveEndpoint(bad_endpoint);
1575   Mock::VerifyAndClearExpectations(&adaptor);
1576 
1577   // Clearing the current endpoint (without removing it) is also safe and sane.
1578   service->NotifyCurrentEndpoint(ok_endpoint);
1579   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, _)).Times(0);
1580   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, _)).Times(0);
1581   EXPECT_CALL(adaptor,
1582               EmitUint8Changed(kSignalStrengthProperty, _)).Times(0);
1583   service->NotifyCurrentEndpoint(nullptr);
1584   Mock::VerifyAndClearExpectations(&adaptor);
1585 }
1586 
TEST_F(WiFiServiceUpdateFromEndpointsTest,EndpointModified)1587 TEST_F(WiFiServiceUpdateFromEndpointsTest, EndpointModified) {
1588   EXPECT_CALL(adaptor, EmitUint16Changed(_, _)).Times(AnyNumber());
1589   EXPECT_CALL(adaptor, EmitStringChanged(_, _)).Times(AnyNumber());
1590   EXPECT_CALL(adaptor, EmitUint8Changed(_, _)).Times(AnyNumber());
1591   EXPECT_CALL(adaptor, EmitBoolChanged(_, _)).Times(AnyNumber());
1592   service->AddEndpoint(ok_endpoint);
1593   service->AddEndpoint(good_endpoint);
1594   EXPECT_EQ(2, service->GetEndpointCount());
1595   Mock::VerifyAndClearExpectations(&adaptor);
1596 
1597   // Updating sub-optimal Endpoint doesn't update Service.
1598   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, _)).Times(0);
1599   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, _)).Times(0);
1600   EXPECT_CALL(adaptor,
1601               EmitUint8Changed(kSignalStrengthProperty, _)).Times(0);
1602   ok_endpoint->signal_strength_ = (kOkEndpointSignal + kGoodEndpointSignal) / 2;
1603   service->NotifyEndpointUpdated(ok_endpoint);
1604   Mock::VerifyAndClearExpectations(&adaptor);
1605 
1606   // Updating optimal Endpoint updates appropriate Service property.
1607   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, _)).Times(0);
1608   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, _)).Times(0);
1609   EXPECT_CALL(adaptor, EmitUint8Changed(kSignalStrengthProperty, _));
1610   good_endpoint->signal_strength_ = kGoodEndpointSignal + 1;
1611   service->NotifyEndpointUpdated(good_endpoint);
1612   Mock::VerifyAndClearExpectations(&adaptor);
1613 
1614   // Change in optimal Endpoint updates Service properties.
1615   EXPECT_CALL(adaptor, EmitUint16Changed(kWifiFrequency, kOkEndpointFrequency));
1616   EXPECT_CALL(adaptor, EmitStringChanged(kWifiBSsid, kOkEndpointBssId));
1617   EXPECT_CALL(adaptor, EmitUint8Changed(kSignalStrengthProperty, _));
1618   ok_endpoint->signal_strength_ = kGoodEndpointSignal + 2;
1619   service->NotifyEndpointUpdated(ok_endpoint);
1620   Mock::VerifyAndClearExpectations(&adaptor);
1621 }
1622 
TEST_F(WiFiServiceUpdateFromEndpointsTest,Ieee80211w)1623 TEST_F(WiFiServiceUpdateFromEndpointsTest, Ieee80211w) {
1624   EXPECT_CALL(adaptor, EmitUint16Changed(_, _)).Times(AnyNumber());
1625   EXPECT_CALL(adaptor, EmitStringChanged(_, _)).Times(AnyNumber());
1626   EXPECT_CALL(adaptor, EmitUint8Changed(_, _)).Times(AnyNumber());
1627   EXPECT_CALL(adaptor, EmitBoolChanged(_, _)).Times(AnyNumber());
1628   service->AddEndpoint(ok_endpoint);
1629   EXPECT_FALSE(service->ieee80211w_required());
1630   good_endpoint->ieee80211w_required_ = true;
1631   service->AddEndpoint(good_endpoint);
1632   EXPECT_TRUE(service->ieee80211w_required());
1633   service->RemoveEndpoint(good_endpoint);
1634   EXPECT_TRUE(service->ieee80211w_required());
1635 }
1636 
TEST_F(WiFiServiceUpdateFromEndpointsTest,PhysicalMode)1637 TEST_F(WiFiServiceUpdateFromEndpointsTest, PhysicalMode) {
1638   EXPECT_CALL(adaptor, EmitUint16Changed(_, _)).Times(AnyNumber());
1639   EXPECT_CALL(adaptor, EmitStringChanged(_, _)).Times(AnyNumber());
1640   EXPECT_CALL(adaptor, EmitUint8Changed(_, _)).Times(AnyNumber());
1641   EXPECT_CALL(adaptor, EmitBoolChanged(_, _)).Times(AnyNumber());
1642 
1643   // No endpoints -> undef.
1644   EXPECT_EQ(Metrics::kWiFiNetworkPhyModeUndef, service->physical_mode());
1645 
1646   // Endpoint has unknown physical mode -> undef.
1647   ok_endpoint->physical_mode_ = Metrics::kWiFiNetworkPhyModeUndef;
1648   service->AddEndpoint(ok_endpoint);
1649   EXPECT_EQ(Metrics::kWiFiNetworkPhyModeUndef, service->physical_mode());
1650 
1651   // New endpoint with 802.11a -> 802.11a.
1652   good_endpoint->physical_mode_ = Metrics::kWiFiNetworkPhyMode11a;
1653   service->AddEndpoint(good_endpoint);
1654   EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11a, service->physical_mode());
1655 
1656   // Remove 802.11a endpoint -> undef.
1657   service->RemoveEndpoint(good_endpoint);
1658   EXPECT_EQ(Metrics::kWiFiNetworkPhyModeUndef, service->physical_mode());
1659 
1660   // Change endpoint -> take endpoint's new value.
1661   ok_endpoint->physical_mode_ = Metrics::kWiFiNetworkPhyMode11n;
1662   service->NotifyEndpointUpdated(ok_endpoint);
1663   EXPECT_EQ(Metrics::kWiFiNetworkPhyMode11n, service->physical_mode());
1664 
1665   // No endpoints -> undef.
1666   service->RemoveEndpoint(ok_endpoint);
1667   EXPECT_EQ(Metrics::kWiFiNetworkPhyModeUndef, service->physical_mode());
1668 }
1669 
TEST_F(WiFiServiceUpdateFromEndpointsTest,WarningOnDisconnect)1670 TEST_F(WiFiServiceUpdateFromEndpointsTest, WarningOnDisconnect) {
1671   service->AddEndpoint(ok_endpoint);
1672   service->SetState(Service::kStateAssociating);
1673   ScopedMockLog log;
1674   EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
1675   EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
1676                        EndsWith("disconnect due to no remaining endpoints.")));
1677   service->RemoveEndpoint(ok_endpoint);
1678 }
1679 
TEST_F(WiFiServiceUpdateFromEndpointsTest,AddEndpointWithPreferredDevice)1680 TEST_F(WiFiServiceUpdateFromEndpointsTest, AddEndpointWithPreferredDevice) {
1681   // Setup service, device, and endpoints.
1682   WiFiServiceRefPtr wifi_service = MakeServiceWithMockManager();
1683   const string kDeviceName1 = "test_device1";
1684   const string kDeviceName2 = "test_device2";
1685   scoped_refptr<MockWiFi> wifi1 = MakeSimpleWiFi(kDeviceName1);
1686   scoped_refptr<MockWiFi> wifi2 = MakeSimpleWiFi(kDeviceName2);
1687   // Best signal for endpoint associated with the preferred device.
1688   const int16_t kPreferredDeviceBestSignal = -40;
1689   WiFiEndpointRefPtr endpoint0 =
1690       MakeOpenEndpointWithWiFi(wifi2, "a", "00:00:00:00:00:01", 0,
1691                                kPreferredDeviceBestSignal + 10);
1692   WiFiEndpointRefPtr endpoint1 =
1693       MakeOpenEndpointWithWiFi(wifi1, "a", "00:00:00:00:00:01", 0,
1694                                kPreferredDeviceBestSignal - 10);
1695   WiFiEndpointRefPtr endpoint2 =
1696       MakeOpenEndpointWithWiFi(wifi1, "a", "00:00:00:00:00:01", 0,
1697                                kPreferredDeviceBestSignal);
1698   WiFiEndpointRefPtr endpoint3 =
1699       MakeOpenEndpointWithWiFi(wifi2, "a", "00:00:00:00:00:01", 0,
1700                                kPreferredDeviceBestSignal + 10);
1701 
1702   wifi_service->SetPreferredDevice(kDeviceName1, nullptr);
1703 
1704   wifi_service->AddEndpoint(endpoint0);
1705   wifi_service->AddEndpoint(endpoint1);
1706   wifi_service->AddEndpoint(endpoint2);
1707   wifi_service->AddEndpoint(endpoint3);
1708   EXPECT_EQ(wifi1, wifi_service->wifi_);
1709   // Service should display the signal strength of the best signal endpoint
1710   // that's associated with the preferred device.
1711   EXPECT_EQ(WiFiService::SignalToStrength(kPreferredDeviceBestSignal),
1712             wifi_service->strength());
1713 }
1714 
1715 MATCHER_P(IsSetwiseEqual, expected_set, "") {
1716   set<uint16_t> arg_set(arg.begin(), arg.end());
1717   return arg_set == expected_set;
1718 }
1719 
TEST_F(WiFiServiceUpdateFromEndpointsTest,FrequencyList)1720 TEST_F(WiFiServiceUpdateFromEndpointsTest, FrequencyList) {
1721   EXPECT_CALL(adaptor, EmitUint16Changed(_, _)).Times(AnyNumber());
1722   EXPECT_CALL(adaptor, EmitStringChanged(_, _)).Times(AnyNumber());
1723   EXPECT_CALL(adaptor, EmitUint8Changed(_, _)).Times(AnyNumber());
1724   EXPECT_CALL(adaptor, EmitBoolChanged(_, _)).Times(AnyNumber());
1725 
1726   // No endpoints -> empty list.
1727   EXPECT_EQ(vector<uint16_t>(), service->frequency_list());
1728 
1729   // Add endpoint -> endpoint's frequency in list.
1730   EXPECT_CALL(adaptor, EmitUint16sChanged(
1731       kWifiFrequencyListProperty, vector<uint16_t>{kGoodEndpointFrequency}));
1732   service->AddEndpoint(good_endpoint);
1733   Mock::VerifyAndClearExpectations(&adaptor);
1734 
1735   // Add another endpoint -> both frequencies in list.
1736   // Order doesn't matter.
1737   set<uint16_t> expected_frequencies{kGoodEndpointFrequency,
1738         kOkEndpointFrequency};
1739   EXPECT_CALL(adaptor, EmitUint16sChanged(
1740       kWifiFrequencyListProperty, IsSetwiseEqual(expected_frequencies)));
1741   service->AddEndpoint(ok_endpoint);
1742   Mock::VerifyAndClearExpectations(&adaptor);
1743 
1744   // Remove endpoint -> other endpoint's frequency remains.
1745   EXPECT_CALL(adaptor, EmitUint16sChanged(
1746       kWifiFrequencyListProperty, vector<uint16_t>{kOkEndpointFrequency}));
1747   service->RemoveEndpoint(good_endpoint);
1748   Mock::VerifyAndClearExpectations(&adaptor);
1749 
1750   // Endpoint with same frequency -> frequency remains.
1751   // Notification may or may not occur -- don't care.
1752   // Frequency may or may not be repeated in list -- don't care.
1753   WiFiEndpointRefPtr same_freq_as_ok_endpoint = MakeOpenEndpoint(
1754       simple_ssid_string(), "aa:bb:cc:dd:ee:ff", ok_endpoint->frequency(), 0);
1755   service->AddEndpoint(same_freq_as_ok_endpoint);
1756   EXPECT_THAT(service->frequency_list(),
1757               IsSetwiseEqual(set<uint16_t>{kOkEndpointFrequency}));
1758   Mock::VerifyAndClearExpectations(&adaptor);
1759 
1760   // Remove endpoint with same frequency -> frequency remains.
1761   // Notification may or may not occur -- don't care.
1762   service->RemoveEndpoint(ok_endpoint);
1763   EXPECT_EQ(vector<uint16_t>{same_freq_as_ok_endpoint->frequency()},
1764             service->frequency_list());
1765   Mock::VerifyAndClearExpectations(&adaptor);
1766 
1767   // Remove last endpoint. Frequency list goes empty.
1768   EXPECT_CALL(adaptor, EmitUint16sChanged(
1769       kWifiFrequencyListProperty, vector<uint16_t>{}));
1770   service->RemoveEndpoint(same_freq_as_ok_endpoint);
1771   Mock::VerifyAndClearExpectations(&adaptor);
1772 }
1773 
TEST_F(WiFiServiceTest,SecurityFromCurrentEndpoint)1774 TEST_F(WiFiServiceTest, SecurityFromCurrentEndpoint) {
1775   WiFiServiceRefPtr service(MakeSimpleService(kSecurityPsk));
1776   EXPECT_EQ(kSecurityPsk, service->GetSecurity(nullptr));
1777   WiFiEndpoint* endpoint = MakeOpenEndpoint(
1778         simple_ssid_string(), "00:00:00:00:00:00", 0, 0);
1779   service->AddEndpoint(endpoint);
1780   EXPECT_EQ(kSecurityPsk, service->GetSecurity(nullptr));
1781   service->NotifyCurrentEndpoint(endpoint);
1782   EXPECT_EQ(kSecurityNone, service->GetSecurity(nullptr));
1783   service->NotifyCurrentEndpoint(nullptr);
1784   EXPECT_EQ(kSecurityPsk, service->GetSecurity(nullptr));
1785 }
1786 
TEST_F(WiFiServiceTest,UpdateSecurity)1787 TEST_F(WiFiServiceTest, UpdateSecurity) {
1788   // Cleartext and pre-shared-key crypto.
1789   {
1790     WiFiServiceRefPtr service = MakeSimpleService(kSecurityNone);
1791     EXPECT_EQ(Service::kCryptoNone, service->crypto_algorithm());
1792     EXPECT_FALSE(service->key_rotation());
1793     EXPECT_FALSE(service->endpoint_auth());
1794   }
1795   {
1796     WiFiServiceRefPtr service = MakeSimpleService(kSecurityWep);
1797     EXPECT_EQ(Service::kCryptoRc4, service->crypto_algorithm());
1798     EXPECT_FALSE(service->key_rotation());
1799     EXPECT_FALSE(service->endpoint_auth());
1800   }
1801   {
1802     WiFiServiceRefPtr service = MakeSimpleService(kSecurityPsk);
1803     EXPECT_EQ(Service::kCryptoRc4, service->crypto_algorithm());
1804     EXPECT_TRUE(service->key_rotation());
1805     EXPECT_FALSE(service->endpoint_auth());
1806   }
1807   {
1808     WiFiServiceRefPtr service = MakeSimpleService(kSecurityWpa);
1809     EXPECT_EQ(Service::kCryptoRc4, service->crypto_algorithm());
1810     EXPECT_TRUE(service->key_rotation());
1811     EXPECT_FALSE(service->endpoint_auth());
1812   }
1813   {
1814     WiFiServiceRefPtr service = MakeSimpleService(kSecurityRsn);
1815     EXPECT_EQ(Service::kCryptoAes, service->crypto_algorithm());
1816     EXPECT_TRUE(service->key_rotation());
1817     EXPECT_FALSE(service->endpoint_auth());
1818   }
1819 
1820   // Crypto with 802.1X key management.
1821   {
1822     // WEP
1823     WiFiServiceRefPtr service = MakeSimpleService(kSecurityWep);
1824     service->SetEAPKeyManagement("IEEE8021X");
1825     EXPECT_EQ(Service::kCryptoRc4, service->crypto_algorithm());
1826     EXPECT_TRUE(service->key_rotation());
1827     EXPECT_TRUE(service->endpoint_auth());
1828   }
1829   {
1830     // WPA
1831     WiFiServiceRefPtr service = MakeSimpleService(kSecurity8021x);
1832     WiFiEndpointRefPtr endpoint =
1833         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, true, false);
1834     service->AddEndpoint(endpoint);
1835     EXPECT_EQ(Service::kCryptoRc4, service->crypto_algorithm());
1836     EXPECT_TRUE(service->key_rotation());
1837     EXPECT_TRUE(service->endpoint_auth());
1838   }
1839   {
1840     // RSN
1841     WiFiServiceRefPtr service = MakeSimpleService(kSecurity8021x);
1842     WiFiEndpointRefPtr endpoint =
1843         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, false, true);
1844     service->AddEndpoint(endpoint);
1845     EXPECT_EQ(Service::kCryptoAes, service->crypto_algorithm());
1846     EXPECT_TRUE(service->key_rotation());
1847     EXPECT_TRUE(service->endpoint_auth());
1848   }
1849   {
1850     // AP supports both WPA and RSN.
1851     WiFiServiceRefPtr service = MakeSimpleService(kSecurity8021x);
1852     WiFiEndpointRefPtr endpoint =
1853         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, true, true);
1854     service->AddEndpoint(endpoint);
1855     EXPECT_EQ(Service::kCryptoAes, service->crypto_algorithm());
1856     EXPECT_TRUE(service->key_rotation());
1857     EXPECT_TRUE(service->endpoint_auth());
1858   }
1859 }
1860 
TEST_F(WiFiServiceTest,ComputeCipher8021x)1861 TEST_F(WiFiServiceTest, ComputeCipher8021x) {
1862   // No endpoints.
1863   {
1864     const set<WiFiEndpointConstRefPtr> endpoints;
1865     EXPECT_EQ(Service::kCryptoNone,
1866               WiFiService::ComputeCipher8021x(endpoints));
1867   }
1868 
1869   // Single endpoint, various configs.
1870   {
1871     set<WiFiEndpointConstRefPtr> endpoints;
1872     endpoints.insert(
1873         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, false, false));
1874     EXPECT_EQ(Service::kCryptoNone,
1875               WiFiService::ComputeCipher8021x(endpoints));
1876   }
1877   {
1878     set<WiFiEndpointConstRefPtr> endpoints;
1879     endpoints.insert(
1880         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, true, false));
1881     EXPECT_EQ(Service::kCryptoRc4,
1882               WiFiService::ComputeCipher8021x(endpoints));
1883   }
1884   {
1885     set<WiFiEndpointConstRefPtr> endpoints;
1886     endpoints.insert(
1887         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, false, true));
1888     EXPECT_EQ(Service::kCryptoAes,
1889               WiFiService::ComputeCipher8021x(endpoints));
1890   }
1891   {
1892     set<WiFiEndpointConstRefPtr> endpoints;
1893     endpoints.insert(
1894         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, true, true));
1895     EXPECT_EQ(Service::kCryptoAes,
1896               WiFiService::ComputeCipher8021x(endpoints));
1897   }
1898 
1899   // Multiple endpoints.
1900   {
1901     set<WiFiEndpointConstRefPtr> endpoints;
1902     endpoints.insert(
1903         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, false, false));
1904     endpoints.insert(
1905         MakeEndpoint("a", "00:00:00:00:00:02", 0, 0, false, false));
1906     EXPECT_EQ(Service::kCryptoNone,
1907               WiFiService::ComputeCipher8021x(endpoints));
1908   }
1909   {
1910     set<WiFiEndpointConstRefPtr> endpoints;
1911     endpoints.insert(
1912         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, false, false));
1913     endpoints.insert(
1914         MakeEndpoint("a", "00:00:00:00:00:02", 0, 0, true, false));
1915     EXPECT_EQ(Service::kCryptoNone,
1916               WiFiService::ComputeCipher8021x(endpoints));
1917   }
1918   {
1919     set<WiFiEndpointConstRefPtr> endpoints;
1920     endpoints.insert(
1921         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, true, false));
1922     endpoints.insert(
1923         MakeEndpoint("a", "00:00:00:00:00:02", 0, 0, true, false));
1924     EXPECT_EQ(Service::kCryptoRc4,
1925               WiFiService::ComputeCipher8021x(endpoints));
1926   }
1927   {
1928     set<WiFiEndpointConstRefPtr> endpoints;
1929     endpoints.insert(
1930         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, true, false));
1931     endpoints.insert(
1932         MakeEndpoint("a", "00:00:00:00:00:02", 0, 0, false, true));
1933     EXPECT_EQ(Service::kCryptoRc4,
1934               WiFiService::ComputeCipher8021x(endpoints));
1935   }
1936   {
1937     set<WiFiEndpointConstRefPtr> endpoints;
1938     endpoints.insert(
1939         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, false, true));
1940     endpoints.insert(
1941         MakeEndpoint("a", "00:00:00:00:00:02", 0, 0, false, true));
1942     EXPECT_EQ(Service::kCryptoAes,
1943               WiFiService::ComputeCipher8021x(endpoints));
1944   }
1945   {
1946     set<WiFiEndpointConstRefPtr> endpoints;
1947     endpoints.insert(
1948         MakeEndpoint("a", "00:00:00:00:00:01", 0, 0, true, true));
1949     endpoints.insert(
1950         MakeEndpoint("a", "00:00:00:00:00:02", 0, 0, true, true));
1951     EXPECT_EQ(Service::kCryptoAes,
1952               WiFiService::ComputeCipher8021x(endpoints));
1953   }
1954 }
1955 
TEST_F(WiFiServiceTest,Unload)1956 TEST_F(WiFiServiceTest, Unload) {
1957   WiFiServiceRefPtr service = MakeServiceWithWiFi(kSecurityNone);
1958   EXPECT_CALL(*wifi(), DestroyIPConfigLease(service->GetStorageIdentifier())).
1959     Times(1);
1960   service->Unload();
1961 }
1962 
TEST_F(WiFiServiceTest,PropertyChanges)1963 TEST_F(WiFiServiceTest, PropertyChanges) {
1964   WiFiServiceRefPtr service = MakeServiceWithMockManager();
1965   ServiceMockAdaptor* adaptor = GetAdaptor(service.get());
1966   TestCommonPropertyChanges(service, adaptor);
1967   TestAutoConnectPropertyChange(service, adaptor);
1968 
1969   EXPECT_CALL(*adaptor,
1970               EmitRpcIdentifierChanged(kDeviceProperty, _));
1971   SetWiFi(service, wifi());
1972   Mock::VerifyAndClearExpectations(adaptor);
1973 
1974   EXPECT_CALL(*adaptor,
1975               EmitRpcIdentifierChanged(kDeviceProperty, _));
1976   service->ResetWiFi();
1977   Mock::VerifyAndClearExpectations(adaptor);
1978 }
1979 
1980 // Custom property setters should return false, and make no changes, if
1981 // the new value is the same as the old value.
TEST_F(WiFiServiceTest,CustomSetterNoopChange)1982 TEST_F(WiFiServiceTest, CustomSetterNoopChange) {
1983   WiFiServiceRefPtr service = MakeServiceWithMockManager();
1984   TestCustomSetterNoopChange(service, mock_manager());
1985 }
1986 
TEST_F(WiFiServiceTest,SuspectedCredentialFailure)1987 TEST_F(WiFiServiceTest, SuspectedCredentialFailure) {
1988   WiFiServiceRefPtr service = MakeSimpleService(kSecurityWpa);
1989   EXPECT_FALSE(service->has_ever_connected());
1990   EXPECT_EQ(0, service->suspected_credential_failures_);
1991 
1992   EXPECT_TRUE(service->AddSuspectedCredentialFailure());
1993   EXPECT_EQ(0, service->suspected_credential_failures_);
1994 
1995   service->has_ever_connected_ = true;
1996   for (int i = 0; i < WiFiService::kSuspectedCredentialFailureThreshold - 1;
1997        ++i) {
1998     EXPECT_FALSE(service->AddSuspectedCredentialFailure());
1999     EXPECT_EQ(i + 1, service->suspected_credential_failures_);
2000   }
2001 
2002   EXPECT_TRUE(service->AddSuspectedCredentialFailure());
2003   // Make sure the failure state does not reset just because we ask again.
2004   EXPECT_TRUE(service->AddSuspectedCredentialFailure());
2005   // Make sure the failure state resets because of a credential change.
2006   // A credential change changes the has_ever_connected to false and
2007   // immediately returns true when attempting to add the failure.
2008   Error error;
2009   service->SetPassphrase("Panchromatic Resonance", &error);
2010   EXPECT_TRUE(error.IsSuccess());
2011   EXPECT_TRUE(service->AddSuspectedCredentialFailure());
2012   EXPECT_EQ(0, service->suspected_credential_failures_);
2013 
2014   // Make sure that we still return true after resetting the failure
2015   // count.
2016   service->suspected_credential_failures_ = 3;
2017   EXPECT_EQ(3, service->suspected_credential_failures_);
2018   service->ResetSuspectedCredentialFailures();
2019   EXPECT_EQ(0, service->suspected_credential_failures_);
2020   EXPECT_TRUE(service->AddSuspectedCredentialFailure());
2021 }
2022 
TEST_F(WiFiServiceTest,GetTethering)2023 TEST_F(WiFiServiceTest, GetTethering) {
2024   WiFiServiceRefPtr service = MakeSimpleService(kSecurityNone);
2025   EXPECT_EQ(kTetheringNotDetectedState, service->GetTethering(nullptr));
2026 
2027   // Since the device isn't connected, we shouldn't even query the WiFi device.
2028   EXPECT_CALL(*wifi(), IsConnectedViaTether()).Times(0);
2029   SetWiFiForService(service, wifi());
2030   EXPECT_EQ(kTetheringNotDetectedState, service->GetTethering(nullptr));
2031   Mock::VerifyAndClearExpectations(wifi().get());
2032 
2033   scoped_refptr<MockProfile> mock_profile(
2034       new NiceMock<MockProfile>(control_interface(), metrics(), manager()));
2035   service->set_profile(mock_profile);
2036   service->SetState(Service::kStateConnected);
2037 
2038   // A connected service should return "confirmed" iff the underlying device
2039   // reports it is tethered.
2040   EXPECT_CALL(*wifi(), IsConnectedViaTether())
2041       .WillOnce(Return(true))
2042       .WillOnce(Return(false));
2043   EXPECT_EQ(kTetheringConfirmedState, service->GetTethering(nullptr));
2044   EXPECT_EQ(kTetheringNotDetectedState, service->GetTethering(nullptr));
2045   Mock::VerifyAndClearExpectations(wifi().get());
2046 
2047   // Add two endpoints that have a BSSID associated with some Android devices
2048   // in tethering mode.
2049   WiFiEndpointRefPtr endpoint_android1 =
2050       MakeOpenEndpoint("a", "02:1a:11:00:00:01", 2412, 0);
2051   service->AddEndpoint(endpoint_android1);
2052   WiFiEndpointRefPtr endpoint_android2 =
2053       MakeOpenEndpoint("a", "02:1a:11:00:00:02", 2412, 0);
2054   service->AddEndpoint(endpoint_android2);
2055 
2056   // Since there are two endpoints, we should not detect tethering mode.
2057   EXPECT_CALL(*wifi(), IsConnectedViaTether()).WillOnce(Return(false));
2058   EXPECT_EQ(kTetheringNotDetectedState, service->GetTethering(nullptr));
2059 
2060   // If the device reports that it is tethered, this should override any
2061   // findings gained from examining the endpoints.
2062   EXPECT_CALL(*wifi(), IsConnectedViaTether()).WillOnce(Return(true));
2063   EXPECT_EQ(kTetheringConfirmedState, service->GetTethering(nullptr));
2064 
2065   // Continue in the un-tethered device case for a few more tests below.
2066   Mock::VerifyAndClearExpectations(wifi().get());
2067   EXPECT_CALL(*wifi(), IsConnectedViaTether())
2068       .WillRepeatedly(Return(false));
2069 
2070   // Removing an endpoint so we only have one should put us in the "Suspected"
2071   // state.
2072   service->RemoveEndpoint(endpoint_android1);
2073   EXPECT_EQ(kTetheringSuspectedState, service->GetTethering(nullptr));
2074 
2075   // Add a different endpoint which has a locally administered MAC address
2076   // but not one used by Android.
2077   service->RemoveEndpoint(endpoint_android2);
2078   WiFiEndpointRefPtr endpoint_ios =
2079       MakeOpenEndpoint("a", "02:00:00:00:00:01", 2412, 0);
2080   service->AddEndpoint(endpoint_ios);
2081   EXPECT_EQ(kTetheringNotDetectedState, service->GetTethering(nullptr));
2082 
2083   // If this endpoint reports the right vendor OUI, we should suspect
2084   // it to be tethered.  However since this evaluation normally only
2085   // happens in the endpoint constructor, we must force it to recalculate.
2086   endpoint_ios->vendor_information_.oui_set.insert(Tethering::kIosOui);
2087   endpoint_ios->CheckForTetheringSignature();
2088   EXPECT_EQ(kTetheringSuspectedState, service->GetTethering(nullptr));
2089 
2090   // If the device reports that it is tethered, this should override any
2091   // findings gained from examining the endpoints.
2092   Mock::VerifyAndClearExpectations(wifi().get());
2093   EXPECT_CALL(*wifi(), IsConnectedViaTether()).WillOnce(Return(true));
2094   EXPECT_EQ(kTetheringConfirmedState, service->GetTethering(nullptr));
2095 }
2096 
TEST_F(WiFiServiceTest,IsVisible)2097 TEST_F(WiFiServiceTest, IsVisible) {
2098   WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(kSecurityNone);
2099   ServiceMockAdaptor* adaptor = GetAdaptor(wifi_service.get());
2100 
2101   // Adding the first endpoint emits a change: Visible = true.
2102   EXPECT_CALL(*adaptor, EmitBoolChanged(kVisibleProperty, true));
2103   WiFiEndpointRefPtr endpoint =
2104       MakeOpenEndpoint("a", "00:00:00:00:00:01", 0, 0);
2105   wifi_service->AddEndpoint(endpoint);
2106   EXPECT_TRUE(wifi_service->IsVisible());
2107   Mock::VerifyAndClearExpectations(adaptor);
2108 
2109   // Removing the last endpoint emits a change: Visible = false.
2110   EXPECT_CALL(*adaptor, EmitBoolChanged(kVisibleProperty, false));
2111   wifi_service->RemoveEndpoint(endpoint);
2112   EXPECT_FALSE(wifi_service->IsVisible());
2113   Mock::VerifyAndClearExpectations(adaptor);
2114 
2115   // Entering the a connecting state emits a change: Visible = true
2116   // although the service has no endpoints.
2117   EXPECT_CALL(*adaptor, EmitBoolChanged(kVisibleProperty, true));
2118   wifi_service->SetState(Service::kStateAssociating);
2119   EXPECT_TRUE(wifi_service->IsVisible());
2120   Mock::VerifyAndClearExpectations(adaptor);
2121 
2122   // Moving between connecting / connected states does not trigger an Emit.
2123   EXPECT_CALL(*adaptor, EmitBoolChanged(kVisibleProperty, _)).Times(0);
2124   wifi_service->SetState(Service::kStateConfiguring);
2125   EXPECT_TRUE(wifi_service->IsVisible());
2126   Mock::VerifyAndClearExpectations(adaptor);
2127 
2128   // Entering the Idle state emits a change: Visible = false.
2129   EXPECT_CALL(*adaptor, EmitBoolChanged(kVisibleProperty, false));
2130   wifi_service->SetState(Service::kStateIdle);
2131   EXPECT_FALSE(wifi_service->IsVisible());
2132   Mock::VerifyAndClearExpectations(adaptor);
2133 }
2134 
TEST_F(WiFiServiceTest,ConfigurePreferredDevice)2135 TEST_F(WiFiServiceTest, ConfigurePreferredDevice) {
2136   const string kDeviceName = "test_device";
2137 
2138   WiFiServiceRefPtr service = MakeGenericService();
2139   KeyValueStore args;
2140   args.SetString(kWifiPreferredDeviceProperty, kDeviceName);
2141 
2142   // With no wifi device.
2143   Error error;
2144   service->Configure(args, &error);
2145   EXPECT_EQ(Error::kSuccess, error.type());
2146   EXPECT_EQ(kDeviceName, service->preferred_device_);
2147 
2148   // With non-preferred wifi device.
2149   SetWiFiForService(service, wifi());
2150   service->Configure(args, &error);
2151   EXPECT_EQ(Error::kSuccess, error.type());
2152   EXPECT_EQ(nullptr, service->wifi_);
2153   EXPECT_EQ(kDeviceName, service->preferred_device_);
2154 
2155   // With preferred wifi device.
2156   scoped_refptr<MockWiFi> preferred_wifi = MakeSimpleWiFi(kDeviceName);
2157   SetWiFiForService(service, preferred_wifi);
2158   service->Configure(args, &error);
2159   EXPECT_EQ(Error::kSuccess, error.type());
2160   EXPECT_EQ(preferred_wifi, service->wifi_);
2161   EXPECT_EQ(kDeviceName, service->preferred_device_);
2162 }
2163 
TEST_F(WiFiServiceTest,LoadAndUnloadPreferredDevice)2164 TEST_F(WiFiServiceTest, LoadAndUnloadPreferredDevice) {
2165   WiFiServiceRefPtr service = MakeGenericService();
2166   NiceMock<MockStore> mock_store;
2167   const string kStorageId = service->GetStorageIdentifier();
2168   EXPECT_CALL(mock_store, ContainsGroup(StrEq(kStorageId)))
2169       .WillRepeatedly(Return(true));
2170   set<string> groups;
2171   groups.insert(kStorageId);
2172   EXPECT_CALL(mock_store, GetGroupsWithProperties(
2173       ContainsWiFiProperties(
2174           simple_ssid(), kModeManaged, kSecurityWep)))
2175       .WillRepeatedly(Return(groups));
2176   EXPECT_CALL(mock_store, GetBool(_, _, _))
2177       .WillRepeatedly(Return(false));
2178   const string kDeviceName = "test_device";
2179   EXPECT_CALL(mock_store,
2180               GetString(StrEq(kStorageId),
2181                         WiFiService::kStoragePreferredDevice, _))
2182       .WillRepeatedly(DoAll(SetArgumentPointee<2>(kDeviceName), Return(true)));
2183   EXPECT_CALL(mock_store,
2184               GetString(StrEq(kStorageId),
2185                         StrNe(WiFiService::kStoragePreferredDevice), _))
2186       .WillRepeatedly(Return(false));
2187 
2188   // With no wifi device.
2189   EXPECT_TRUE(service->Load(&mock_store));
2190   EXPECT_EQ(kDeviceName, service->preferred_device_);
2191   service->Unload();
2192   EXPECT_EQ("", service->preferred_device_);
2193 
2194   // With non-preferred wifi device.
2195   SetWiFiForService(service, wifi());
2196   EXPECT_TRUE(service->Load(&mock_store));
2197   EXPECT_EQ(nullptr, service->wifi_);
2198   EXPECT_EQ(kDeviceName, service->preferred_device_);
2199   service->Unload();
2200   EXPECT_EQ("", service->preferred_device_);
2201 
2202   // With preferred wifi device.
2203   scoped_refptr<MockWiFi> preferred_wifi = MakeSimpleWiFi(kDeviceName);
2204   SetWiFiForService(service, preferred_wifi);
2205   EXPECT_TRUE(service->Load(&mock_store));
2206   EXPECT_EQ(preferred_wifi, service->wifi_);
2207   EXPECT_EQ(kDeviceName, service->preferred_device_);
2208   service->Unload();
2209   EXPECT_EQ("", service->preferred_device_);
2210 }
2211 
TEST_F(WiFiServiceTest,ChooseDevice)2212 TEST_F(WiFiServiceTest, ChooseDevice) {
2213   const string kDeviceName1 = "test_device1";
2214   const string kDeviceName2 = "test_device2";
2215   scoped_refptr<MockWiFi> wifi1 = MakeSimpleWiFi(kDeviceName1);
2216   scoped_refptr<MockWiFi> wifi2 = MakeSimpleWiFi(kDeviceName2);
2217   WiFiServiceRefPtr service = MakeServiceWithMockManager();
2218 
2219   // No preferred device.
2220   EXPECT_CALL(*mock_manager(), GetEnabledDeviceByLinkName(_)).Times(0);
2221   EXPECT_CALL(*mock_manager(),
2222               GetEnabledDeviceWithTechnology(Technology::kWifi))
2223       .WillOnce(Return(wifi1));
2224   EXPECT_EQ(wifi1, service->ChooseDevice());
2225   Mock::VerifyAndClearExpectations(mock_manager());
2226 
2227   // With preferred device.
2228   service->SetPreferredDevice(kDeviceName2, nullptr);
2229   EXPECT_CALL(*mock_manager(), GetEnabledDeviceByLinkName(kDeviceName2))
2230       .WillOnce(Return(wifi2));
2231   EXPECT_CALL(*mock_manager(), GetEnabledDeviceWithTechnology(_)).Times(0);
2232   EXPECT_EQ(wifi2, service->ChooseDevice());
2233   Mock::VerifyAndClearExpectations(mock_manager());
2234 }
2235 
TEST_F(WiFiServiceTest,RoamThresholdProperty)2236 TEST_F(WiFiServiceTest, RoamThresholdProperty) {
2237   WiFiServiceRefPtr service = MakeGenericService();
2238   static const uint16_t kRoamThreshold16 = 16;
2239   static const uint16_t kRoamThreshold32 = 32;
2240 
2241   EXPECT_TRUE(SetRoamThreshold(service, kRoamThreshold16));
2242   EXPECT_EQ(GetRoamThreshold(service), kRoamThreshold16);
2243 
2244   // Try a different number
2245   EXPECT_TRUE(SetRoamThreshold(service, kRoamThreshold32));
2246   EXPECT_EQ(GetRoamThreshold(service), kRoamThreshold32);
2247 }
2248 
TEST_F(WiFiServiceTest,SaveLoadRoamThreshold)2249 TEST_F(WiFiServiceTest, SaveLoadRoamThreshold) {
2250   WiFiServiceRefPtr service = MakeGenericService();
2251   NiceMock<MockStore> mock_store;
2252   const uint16_t kRoamThreshold = 10;
2253   const string kStorageId = service->GetStorageIdentifier();
2254   EXPECT_CALL(mock_store, ContainsGroup(StrEq(kStorageId)))
2255       .WillRepeatedly(Return(true));
2256   set<string> groups;
2257   groups.insert(kStorageId);
2258   EXPECT_CALL(mock_store, GetGroupsWithProperties(ContainsWiFiProperties(
2259                               simple_ssid(), kModeManaged, kSecurityWep)))
2260       .WillRepeatedly(Return(groups));
2261   EXPECT_CALL(mock_store, GetBool(_, _, _)).Times(AnyNumber());
2262   EXPECT_CALL(mock_store, SetBool(_, _, _)).Times(AnyNumber());
2263 
2264   // First, save these values.
2265   service->roam_threshold_db_ = kRoamThreshold;
2266   service->roam_threshold_db_set_ = true;
2267   EXPECT_CALL(mock_store,
2268               SetUint64(StrEq(kStorageId), WiFiService::kStorageRoamThreshold,
2269                         kRoamThreshold));
2270   EXPECT_CALL(mock_store, SetBool(StrEq(kStorageId),
2271                                   WiFiService::kStorageRoamThresholdSet, true));
2272   EXPECT_TRUE(service->Save(&mock_store));
2273 
2274   // Then, load these values into the WiFiService members.
2275   service->roam_threshold_db_ = 0;
2276   service->roam_threshold_db_set_ = false;
2277   EXPECT_CALL(mock_store, GetUint64(StrEq(kStorageId),
2278                                     WiFiService::kStorageRoamThreshold, _))
2279       .WillOnce(DoAll(SetArgumentPointee<2>(kRoamThreshold), Return(true)));
2280   EXPECT_CALL(mock_store, GetBool(StrEq(kStorageId),
2281                                   WiFiService::kStorageRoamThresholdSet, _))
2282       .WillOnce(DoAll(SetArgumentPointee<2>(true), Return(true)));
2283   EXPECT_TRUE(service->Load(&mock_store));
2284   EXPECT_EQ(kRoamThreshold, service->roam_threshold_db_);
2285   EXPECT_TRUE(service->roam_threshold_db_set_);
2286 }
2287 
2288 }  // namespace shill
2289