| // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "shill/wifi.h" |
| |
| #include <netinet/ether.h> |
| #include <linux/if.h> |
| #include <sys/socket.h> |
| #include <linux/netlink.h> // Needs typedefs from sys/socket.h. |
| |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include <base/memory/ref_counted.h> |
| #include <base/memory/scoped_ptr.h> |
| #include <base/stringprintf.h> |
| #include <base/string_number_conversions.h> |
| #include <base/string_split.h> |
| #include <base/string_util.h> |
| #include <chromeos/dbus/service_constants.h> |
| #include <dbus-c++/dbus.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "shill/dbus_adaptor.h" |
| #include "shill/event_dispatcher.h" |
| #include "shill/ieee80211.h" |
| #include "shill/key_value_store.h" |
| #include "shill/logging.h" |
| #include "shill/manager.h" |
| #include "shill/mock_dbus_manager.h" |
| #include "shill/mock_device.h" |
| #include "shill/mock_device_info.h" |
| #include "shill/mock_dhcp_config.h" |
| #include "shill/mock_dhcp_provider.h" |
| #include "shill/mock_event_dispatcher.h" |
| #include "shill/mock_link_monitor.h" |
| #include "shill/mock_log.h" |
| #include "shill/mock_manager.h" |
| #include "shill/mock_metrics.h" |
| #include "shill/mock_profile.h" |
| #include "shill/mock_rtnl_handler.h" |
| #include "shill/mock_store.h" |
| #include "shill/mock_supplicant_bss_proxy.h" |
| #include "shill/mock_supplicant_interface_proxy.h" |
| #include "shill/mock_supplicant_process_proxy.h" |
| #include "shill/mock_time.h" |
| #include "shill/mock_wifi_service.h" |
| #include "shill/nice_mock_control.h" |
| #include "shill/property_store_inspector.h" |
| #include "shill/property_store_unittest.h" |
| #include "shill/proxy_factory.h" |
| #include "shill/wifi_endpoint.h" |
| #include "shill/wifi_service.h" |
| #include "shill/wpa_supplicant.h" |
| |
| |
| using std::map; |
| using std::set; |
| using std::string; |
| using std::vector; |
| using ::testing::_; |
| using ::testing::AnyNumber; |
| using ::testing::DefaultValue; |
| using ::testing::DoAll; |
| using ::testing::EndsWith; |
| using ::testing::InSequence; |
| using ::testing::Invoke; |
| using ::testing::InvokeWithoutArgs; |
| using ::testing::Mock; |
| using ::testing::NiceMock; |
| using ::testing::Return; |
| using ::testing::SaveArg; |
| using ::testing::SetArgumentPointee; |
| using ::testing::StrEq; |
| using ::testing::StrictMock; |
| using ::testing::Test; |
| using ::testing::Throw; |
| using ::testing::Values; |
| |
| namespace shill { |
| |
| class WiFiPropertyTest : public PropertyStoreTest { |
| public: |
| WiFiPropertyTest() |
| : device_(new WiFi(control_interface(), |
| NULL, NULL, NULL, "wifi", "", 0)) { |
| } |
| virtual ~WiFiPropertyTest() {} |
| |
| protected: |
| WiFiRefPtr device_; |
| }; |
| |
| TEST_F(WiFiPropertyTest, Contains) { |
| EXPECT_TRUE(device_->store().Contains(flimflam::kNameProperty)); |
| EXPECT_FALSE(device_->store().Contains("")); |
| } |
| |
| TEST_F(WiFiPropertyTest, SetProperty) { |
| { |
| ::DBus::Error error; |
| EXPECT_TRUE(DBusAdaptor::SetProperty( |
| device_->mutable_store(), |
| flimflam::kBgscanSignalThresholdProperty, |
| PropertyStoreTest::kInt32V, |
| &error)); |
| } |
| { |
| ::DBus::Error error; |
| EXPECT_TRUE(DBusAdaptor::SetProperty(device_->mutable_store(), |
| flimflam::kScanIntervalProperty, |
| PropertyStoreTest::kUint16V, |
| &error)); |
| } |
| // Ensure that an attempt to write a R/O property returns InvalidArgs error. |
| { |
| ::DBus::Error error; |
| EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(), |
| flimflam::kScanningProperty, |
| PropertyStoreTest::kBoolV, |
| &error)); |
| EXPECT_EQ(invalid_args(), error.name()); |
| } |
| |
| { |
| ::DBus::Error error; |
| EXPECT_TRUE(DBusAdaptor::SetProperty( |
| device_->mutable_store(), |
| flimflam::kBgscanMethodProperty, |
| DBusAdaptor::StringToVariant( |
| wpa_supplicant::kNetworkBgscanMethodSimple), |
| &error)); |
| } |
| |
| { |
| ::DBus::Error error; |
| EXPECT_FALSE(DBusAdaptor::SetProperty( |
| device_->mutable_store(), |
| flimflam::kBgscanMethodProperty, |
| DBusAdaptor::StringToVariant("not a real scan method"), |
| &error)); |
| } |
| } |
| |
| TEST_F(WiFiPropertyTest, BgscanMethodProperty) { |
| EXPECT_NE(wpa_supplicant::kNetworkBgscanMethodLearn, |
| WiFi::kDefaultBgscanMethod); |
| EXPECT_TRUE(device_->bgscan_method_.empty()); |
| |
| string method; |
| PropertyStoreInspector inspector(&device_->store()); |
| EXPECT_TRUE(inspector.GetStringProperty(flimflam::kBgscanMethodProperty, |
| &method)); |
| EXPECT_EQ(WiFi::kDefaultBgscanMethod, method); |
| EXPECT_EQ(wpa_supplicant::kNetworkBgscanMethodSimple, method); |
| |
| ::DBus::Error error; |
| EXPECT_TRUE(DBusAdaptor::SetProperty( |
| device_->mutable_store(), |
| flimflam::kBgscanMethodProperty, |
| DBusAdaptor::StringToVariant( |
| wpa_supplicant::kNetworkBgscanMethodLearn), |
| &error)); |
| EXPECT_EQ(wpa_supplicant::kNetworkBgscanMethodLearn, device_->bgscan_method_); |
| EXPECT_TRUE(inspector.GetStringProperty(flimflam::kBgscanMethodProperty, |
| &method)); |
| EXPECT_EQ(wpa_supplicant::kNetworkBgscanMethodLearn, method); |
| |
| EXPECT_TRUE(DBusAdaptor::ClearProperty( |
| device_->mutable_store(), flimflam::kBgscanMethodProperty, &error)); |
| EXPECT_TRUE(inspector.GetStringProperty(flimflam::kBgscanMethodProperty, |
| &method)); |
| EXPECT_EQ(WiFi::kDefaultBgscanMethod, method); |
| EXPECT_TRUE(device_->bgscan_method_.empty()); |
| } |
| |
| class WiFiObjectTest : public ::testing::TestWithParam<string> { |
| public: |
| WiFiObjectTest(EventDispatcher *dispatcher) |
| : event_dispatcher_(dispatcher), |
| manager_(&control_interface_, NULL, &metrics_, &glib_), |
| device_info_(&control_interface_, dispatcher, &metrics_, &manager_), |
| wifi_(new WiFi(&control_interface_, |
| dispatcher, |
| &metrics_, |
| &manager_, |
| kDeviceName, |
| kDeviceAddress, |
| 0)), |
| supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()), |
| supplicant_interface_proxy_( |
| new NiceMock<MockSupplicantInterfaceProxy>(wifi_)), |
| supplicant_bss_proxy_( |
| new NiceMock<MockSupplicantBSSProxy>()), |
| dhcp_config_(new MockDHCPConfig(&control_interface_, |
| kDeviceName)), |
| dbus_manager_(new NiceMock<MockDBusManager>()), |
| proxy_factory_(this) { |
| ::testing::DefaultValue< ::DBus::Path>::Set("/default/path"); |
| // Except for WiFiServices created via WiFi::GetService, we expect |
| // that any WiFiService has been registered with the Manager. So |
| // default Manager.HasService to true, to make the common case |
| // easy. |
| ON_CALL(manager_, HasService(_)). |
| WillByDefault(Return(true)); |
| |
| ON_CALL(dhcp_provider_, CreateConfig(_, _, _, _)). |
| WillByDefault(Return(dhcp_config_)); |
| ON_CALL(*dhcp_config_.get(), RequestIP()). |
| WillByDefault(Return(true)); |
| |
| manager_.dbus_manager_.reset(dbus_manager_); // Transfers ownership. |
| |
| wifi_->time_ = &time_; |
| } |
| |
| virtual void SetUp() { |
| // EnableScopes... so that we can EXPECT_CALL for scoped log messages. |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(3); |
| wifi_->proxy_factory_ = &proxy_factory_; |
| static_cast<Device *>(wifi_)->rtnl_handler_ = &rtnl_handler_; |
| wifi_->set_dhcp_provider(&dhcp_provider_); |
| ON_CALL(manager_, device_info()). |
| WillByDefault(Return(&device_info_)); |
| EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(AnyNumber()); |
| EXPECT_CALL(manager_, DeregisterService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*supplicant_bss_proxy_, Die()).Times(AnyNumber()); |
| } |
| |
| virtual void TearDown() { |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| wifi_->SelectService(NULL); |
| if (supplicant_bss_proxy_.get()) { |
| EXPECT_CALL(*supplicant_bss_proxy_, Die()); |
| } |
| wifi_->proxy_factory_ = NULL; |
| // must Stop WiFi instance, to clear its list of services. |
| // otherwise, the WiFi instance will not be deleted. (because |
| // services reference a WiFi instance, creating a cycle.) |
| wifi_->Stop(NULL, ResultCallback()); |
| wifi_->set_dhcp_provider(NULL); |
| // Reset scope logging, to avoid interfering with other tests. |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| } |
| |
| // Needs to be public since it is called via Invoke(). |
| void StopWiFi() { |
| wifi_->SetEnabled(false); // Stop(NULL, ResultCallback()); |
| } |
| |
| void UnloadService(const ServiceRefPtr &service) { |
| service->Unload(); |
| } |
| |
| protected: |
| typedef scoped_refptr<MockWiFiService> MockWiFiServiceRefPtr; |
| |
| class TestProxyFactory : public ProxyFactory { |
| public: |
| explicit TestProxyFactory(WiFiObjectTest *test); |
| |
| virtual SupplicantProcessProxyInterface *CreateSupplicantProcessProxy( |
| const char */*dbus_path*/, const char */*dbus_addr*/) { |
| return test_->supplicant_process_proxy_.release(); |
| } |
| |
| virtual SupplicantInterfaceProxyInterface *CreateSupplicantInterfaceProxy( |
| const WiFiRefPtr &/*wifi*/, |
| const DBus::Path &/*object_path*/, |
| const char */*dbus_addr*/) { |
| return test_->supplicant_interface_proxy_.release(); |
| } |
| |
| MOCK_METHOD3(CreateSupplicantBSSProxy, |
| SupplicantBSSProxyInterface *( |
| WiFiEndpoint *wifi_endpoint, |
| const DBus::Path &object_path, |
| const char *dbus_addr)); |
| |
| private: |
| SupplicantBSSProxyInterface *CreateSupplicantBSSProxyInternal( |
| WiFiEndpoint */*wifi_endpoint*/, |
| const DBus::Path &/*object_path*/, |
| const char */*dbus_addr*/) { |
| return test_->supplicant_bss_proxy_.release(); |
| } |
| |
| WiFiObjectTest *test_; |
| }; |
| |
| void CancelScanTimer() { |
| wifi_->scan_timer_callback_.Cancel(); |
| } |
| WiFiServiceRefPtr CreateServiceForEndpoint(const WiFiEndpoint &endpoint) { |
| bool hidden_ssid = false; |
| return wifi_->CreateServiceForEndpoint(endpoint, hidden_ssid); |
| } |
| void FireScanTimer() { |
| wifi_->ScanTimerHandler(); |
| } |
| const WiFiServiceRefPtr &GetCurrentService() { |
| return wifi_->current_service_; |
| } |
| void SetCurrentService(const WiFiServiceRefPtr &service) { |
| wifi_->current_service_ = service; |
| } |
| const WiFi::EndpointMap &GetEndpointMap() { |
| return wifi_->endpoint_by_rpcid_; |
| } |
| const WiFiServiceRefPtr &GetPendingService() { |
| return wifi_->pending_service_; |
| } |
| const base::CancelableClosure &GetPendingTimeout() { |
| return wifi_->pending_timeout_callback_; |
| } |
| const base::CancelableClosure &GetReconnectTimeoutCallback() { |
| return wifi_->reconnect_timeout_callback_; |
| } |
| int GetReconnectTimeoutSeconds() { |
| return WiFi::kReconnectTimeoutSeconds; |
| } |
| const base::CancelableClosure &GetScanTimer() { |
| return wifi_->scan_timer_callback_; |
| } |
| const vector<WiFiServiceRefPtr> &GetServices() { |
| return wifi_->services_; |
| } |
| // note: the tests need the proxies referenced by WiFi (not the |
| // proxies instantiated by WiFiObjectTest), to ensure that WiFi |
| // sets up its proxies correctly. |
| SupplicantProcessProxyInterface *GetSupplicantProcessProxy() { |
| return wifi_->supplicant_process_proxy_.get(); |
| } |
| MockSupplicantInterfaceProxy *GetSupplicantInterfaceProxy() { |
| return dynamic_cast<MockSupplicantInterfaceProxy *>( |
| wifi_->supplicant_interface_proxy_.get()); |
| } |
| const string &GetSupplicantState() { |
| return wifi_->supplicant_state_; |
| } |
| void InitiateConnect(WiFiServiceRefPtr service) { |
| map<string, ::DBus::Variant> params; |
| wifi_->ConnectTo(service, params); |
| } |
| void InitiateDisconnect(WiFiServiceRefPtr service) { |
| wifi_->DisconnectFrom(service); |
| } |
| WiFiEndpointRefPtr MakeEndpoint(const string &ssid, const string &bssid) { |
| return WiFiEndpoint::MakeOpenEndpoint( |
| &proxy_factory_, NULL, ssid, bssid, 0, 0); |
| } |
| MockWiFiServiceRefPtr MakeMockService(const std::string &security) { |
| vector<uint8_t> ssid(1, 'a'); |
| return new MockWiFiService( |
| &control_interface_, |
| event_dispatcher_, |
| &metrics_, |
| &manager_, |
| wifi_, |
| ssid, |
| flimflam::kModeManaged, |
| security, |
| false); |
| } |
| void RemoveBSS(const ::DBus::Path &bss_path); |
| void ReportBSS(const ::DBus::Path &bss_path, |
| const string &ssid, |
| const string &bssid, |
| int16_t signal_strength, |
| uint16 frequency, |
| const char *mode); |
| void ClearCachedCredentials() { |
| wifi_->ClearCachedCredentials(); |
| } |
| void ReportIPConfigComplete() { |
| wifi_->OnIPConfigUpdated(dhcp_config_, true); |
| } |
| void ReportLinkUp() { |
| wifi_->LinkEvent(IFF_LOWER_UP, IFF_LOWER_UP); |
| } |
| void ReportScanDone() { |
| wifi_->ScanDoneTask(); |
| } |
| void ReportCurrentBSSChanged(const string &new_bss) { |
| wifi_->CurrentBSSChanged(new_bss); |
| } |
| void ReportStateChanged(const string &new_state) { |
| wifi_->StateChanged(new_state); |
| } |
| void SetPendingService(const WiFiServiceRefPtr &service) { |
| wifi_->pending_service_ = service; |
| } |
| void SetScanInterval(uint16_t interval_seconds) { |
| wifi_->SetScanInterval(interval_seconds, NULL); |
| } |
| uint16_t GetScanInterval() { |
| return wifi_->GetScanInterval(NULL); |
| } |
| void StartWiFi(bool supplicant_present) { |
| wifi_->supplicant_present_ = supplicant_present; |
| wifi_->SetEnabled(true); // Start(NULL, ResultCallback()); |
| } |
| void StartWiFi() { |
| StartWiFi(true); |
| } |
| void OnAfterResume() { |
| wifi_->OnAfterResume(); |
| } |
| void OnBeforeSuspend() { |
| wifi_->OnBeforeSuspend(); |
| } |
| void OnSupplicantAppear() { |
| wifi_->OnSupplicantAppear(":1.7"); |
| EXPECT_TRUE(wifi_->supplicant_present_); |
| } |
| void OnSupplicantVanish() { |
| wifi_->OnSupplicantVanish(); |
| EXPECT_FALSE(wifi_->supplicant_present_); |
| } |
| bool GetSupplicantPresent() { |
| return wifi_->supplicant_present_; |
| } |
| WiFiServiceRefPtr GetOpenService(const char *service_type, |
| const char *ssid, |
| const char *mode, |
| Error *result) { |
| return GetServiceInner(service_type, ssid, mode, NULL, NULL, false, result); |
| } |
| WiFiServiceRefPtr GetService(const char *service_type, |
| const char *ssid, |
| const char *mode, |
| const char *security, |
| const char *passphrase, |
| Error *result) { |
| return GetServiceInner(service_type, ssid, mode, security, passphrase, |
| false, result); |
| } |
| WiFiServiceRefPtr GetServiceInner(const char *service_type, |
| const char *ssid, |
| const char *mode, |
| const char *security, |
| const char *passphrase, |
| bool allow_hidden, |
| Error *result) { |
| map<string, ::DBus::Variant> args; |
| // in general, we want to avoid D-Bus specific code for any RPCs |
| // that come in via adaptors. we make an exception here, because |
| // calls to GetWifiService are rerouted from the Manager object to |
| // the Wifi class. |
| if (service_type != NULL) |
| args[flimflam::kTypeProperty].writer().append_string(service_type); |
| if (ssid != NULL) |
| args[flimflam::kSSIDProperty].writer().append_string(ssid); |
| if (mode != NULL) |
| args[flimflam::kModeProperty].writer().append_string(mode); |
| if (security != NULL) |
| args[flimflam::kSecurityProperty].writer().append_string(security); |
| if (passphrase != NULL) |
| args[flimflam::kPassphraseProperty].writer().append_string(passphrase); |
| if (!allow_hidden) |
| args[flimflam::kWifiHiddenSsid].writer().append_bool(false); |
| |
| Error e; |
| KeyValueStore args_kv; |
| DBusAdaptor::ArgsToKeyValueStore(args, &args_kv, &e); |
| return wifi_->GetService(args_kv, result); |
| } |
| |
| WiFiServiceRefPtr GetServiceWithKeyValues(const KeyValueStore &args, |
| Error *result) { |
| return wifi_->GetService(args, result); |
| } |
| |
| WiFiServiceRefPtr FindService(const vector<uint8_t> &ssid, |
| const string &mode, |
| const string &security) { |
| return wifi_->FindService(ssid, mode, security); |
| } |
| bool LoadHiddenServices(StoreInterface *storage) { |
| return wifi_->LoadHiddenServices(storage); |
| } |
| void SetupHiddenStorage(MockStore *storage, const string &ssid, string *id) { |
| const string hex_ssid = base::HexEncode(ssid.data(), ssid.size()); |
| *id = StringToLowerASCII(base::StringPrintf("%s_%s_%s_%s_%s", |
| flimflam::kTypeWifi, |
| kDeviceAddress, |
| hex_ssid.c_str(), |
| flimflam::kModeManaged, |
| flimflam::kSecurityNone)); |
| const char *groups[] = { id->c_str() }; |
| EXPECT_CALL(*storage, GetGroupsWithKey(flimflam::kWifiHiddenSsid)) |
| .WillRepeatedly(Return(set<string>(groups, groups + 1))); |
| EXPECT_CALL(*storage, GetBool(StrEq(*id), flimflam::kWifiHiddenSsid, _)) |
| .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true))); |
| EXPECT_CALL(*storage, GetString(StrEq(*id), flimflam::kSSIDProperty, _)) |
| .WillRepeatedly(DoAll(SetArgumentPointee<2>(hex_ssid), Return(true))); |
| } |
| |
| WiFiService *SetupConnectedService(const DBus::Path &network_path) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| if (!network_path.empty()) { |
| EXPECT_CALL(*supplicant_interface_proxy_, AddNetwork(_)) |
| .WillOnce(Return(network_path)); |
| } |
| |
| StartWiFi(); |
| ReportBSS(kBSSName, kSSIDName, "00:00:00:00:00:00", 0, 0, |
| kNetworkModeAdHoc); |
| WiFiService *service(GetServices().begin()->get()); |
| EXPECT_TRUE(GetPendingTimeout().IsCancelled()); |
| InitiateConnect(service); |
| EXPECT_FALSE(GetPendingTimeout().IsCancelled()); |
| ReportCurrentBSSChanged(kBSSName); |
| EXPECT_TRUE(GetPendingTimeout().IsCancelled()); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| |
| EXPECT_EQ(service, GetCurrentService()); |
| |
| return service; |
| } |
| |
| bool SetBgscanMethod(const string &method) { |
| ::DBus::Error error; |
| return DBusAdaptor::SetProperty( |
| wifi_->mutable_store(), |
| flimflam::kBgscanMethodProperty, |
| DBusAdaptor::StringToVariant(method), |
| &error); |
| } |
| |
| void AppendBgscan(WiFiService *service, |
| std::map<std::string, DBus::Variant> *service_params) { |
| wifi_->AppendBgscan(service, service_params); |
| } |
| |
| void ReportCertification(const map<string, ::DBus::Variant> &properties) { |
| wifi_->CertificationTask(properties); |
| } |
| |
| void RestartFastScanAttempts() { |
| wifi_->RestartFastScanAttempts(); |
| } |
| |
| void StartReconnectTimer() { |
| wifi_->StartReconnectTimer(); |
| } |
| |
| void StopReconnectTimer() { |
| wifi_->StopReconnectTimer(); |
| } |
| |
| void SetLinkMonitor(LinkMonitor *link_monitor) { |
| wifi_->set_link_monitor(link_monitor); |
| } |
| |
| void OnLinkMonitorFailure() { |
| wifi_->OnLinkMonitorFailure(); |
| } |
| |
| NiceMockControl *control_interface() { |
| return &control_interface_; |
| } |
| |
| MockManager *manager() { |
| return &manager_; |
| } |
| |
| MockDeviceInfo *device_info() { |
| return &device_info_; |
| } |
| |
| MockDHCPProvider *dhcp_provider() { |
| return &dhcp_provider_; |
| } |
| |
| const WiFiConstRefPtr wifi() const { |
| return wifi_; |
| } |
| |
| TestProxyFactory *proxy_factory() { |
| return &proxy_factory_; |
| } |
| |
| EventDispatcher *event_dispatcher_; |
| NiceMock<MockRTNLHandler> rtnl_handler_; |
| MockTime time_; |
| |
| private: |
| NiceMockControl control_interface_; |
| MockMetrics metrics_; |
| MockGLib glib_; |
| MockManager manager_; |
| MockDeviceInfo device_info_; |
| WiFiRefPtr wifi_; |
| |
| // protected fields interspersed between private fields, due to |
| // initialization order |
| protected: |
| static const char kDeviceName[]; |
| static const char kDeviceAddress[]; |
| static const char kNetworkModeAdHoc[]; |
| static const char kNetworkModeInfrastructure[]; |
| static const char kBSSName[]; |
| static const char kSSIDName[]; |
| |
| scoped_ptr<MockSupplicantProcessProxy> supplicant_process_proxy_; |
| scoped_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_; |
| scoped_ptr<MockSupplicantBSSProxy> supplicant_bss_proxy_; |
| MockDHCPProvider dhcp_provider_; |
| scoped_refptr<MockDHCPConfig> dhcp_config_; |
| NiceMock<MockDBusManager> *dbus_manager_; |
| |
| private: |
| TestProxyFactory proxy_factory_; |
| }; |
| |
| const char WiFiObjectTest::kDeviceName[] = "wlan0"; |
| const char WiFiObjectTest::kDeviceAddress[] = "000102030405"; |
| const char WiFiObjectTest::kNetworkModeAdHoc[] = "ad-hoc"; |
| const char WiFiObjectTest::kNetworkModeInfrastructure[] = "infrastructure"; |
| const char WiFiObjectTest::kBSSName[] = "bss0"; |
| const char WiFiObjectTest::kSSIDName[] = "ssid0"; |
| |
| void WiFiObjectTest::RemoveBSS(const ::DBus::Path &bss_path) { |
| wifi_->BSSRemovedTask(bss_path); |
| } |
| |
| void WiFiObjectTest::ReportBSS(const ::DBus::Path &bss_path, |
| const string &ssid, |
| const string &bssid, |
| int16_t signal_strength, |
| uint16 frequency, |
| const char *mode) { |
| map<string, ::DBus::Variant> bss_properties; |
| |
| { |
| DBus::MessageIter writer(bss_properties["SSID"].writer()); |
| writer << vector<uint8_t>(ssid.begin(), ssid.end()); |
| } |
| { |
| string bssid_nosep; |
| vector<uint8_t> bssid_bytes; |
| RemoveChars(bssid, ":", &bssid_nosep); |
| base::HexStringToBytes(bssid_nosep, &bssid_bytes); |
| |
| DBus::MessageIter writer(bss_properties["BSSID"].writer()); |
| writer << bssid_bytes; |
| } |
| bss_properties[wpa_supplicant::kBSSPropertySignal].writer(). |
| append_int16(signal_strength); |
| bss_properties[wpa_supplicant::kBSSPropertyFrequency].writer(). |
| append_uint16(frequency); |
| bss_properties[wpa_supplicant::kBSSPropertyMode].writer().append_string(mode); |
| wifi_->BSSAddedTask(bss_path, bss_properties); |
| } |
| |
| WiFiObjectTest::TestProxyFactory::TestProxyFactory(WiFiObjectTest *test) |
| : test_(test) { |
| EXPECT_CALL(*this, CreateSupplicantBSSProxy(_, _, _)).Times(AnyNumber()); |
| ON_CALL(*this, CreateSupplicantBSSProxy(_, _, _)) |
| .WillByDefault( |
| Invoke(this, (&TestProxyFactory::CreateSupplicantBSSProxyInternal))); |
| } |
| |
| // Most of our tests involve using a real EventDispatcher object. |
| class WiFiMainTest : public WiFiObjectTest { |
| public: |
| WiFiMainTest() : WiFiObjectTest(&dispatcher_) {} |
| |
| protected: |
| EventDispatcher dispatcher_; |
| }; |
| |
| TEST_F(WiFiMainTest, ProxiesSetUpDuringStart) { |
| EXPECT_TRUE(GetSupplicantProcessProxy() == NULL); |
| EXPECT_TRUE(GetSupplicantInterfaceProxy() == NULL); |
| |
| StartWiFi(); |
| EXPECT_FALSE(GetSupplicantProcessProxy() == NULL); |
| EXPECT_FALSE(GetSupplicantInterfaceProxy() == NULL); |
| } |
| |
| TEST_F(WiFiMainTest, SupplicantPresent) { |
| EXPECT_FALSE(GetSupplicantPresent()); |
| } |
| |
| TEST_F(WiFiMainTest, OnSupplicantAppearStarted) { |
| EXPECT_TRUE(GetSupplicantProcessProxy() == NULL); |
| |
| EXPECT_CALL(*dbus_manager_, WatchName(wpa_supplicant::kDBusAddr, _, _)); |
| StartWiFi(false); // No supplicant present. |
| EXPECT_TRUE(GetSupplicantProcessProxy() == NULL); |
| |
| OnSupplicantAppear(); |
| EXPECT_FALSE(GetSupplicantProcessProxy() == NULL); |
| |
| // If supplicant reappears while the device is started, the device should be |
| // restarted. |
| EXPECT_CALL(*manager(), DeregisterDevice(_)); |
| EXPECT_CALL(*manager(), RegisterDevice(_)); |
| OnSupplicantAppear(); |
| } |
| |
| TEST_F(WiFiMainTest, OnSupplicantAppearStopped) { |
| EXPECT_TRUE(GetSupplicantProcessProxy() == NULL); |
| |
| OnSupplicantAppear(); |
| EXPECT_TRUE(GetSupplicantProcessProxy() == NULL); |
| |
| // If supplicant reappears while the device is stopped, the device should not |
| // be restarted. |
| EXPECT_CALL(*manager(), DeregisterDevice(_)).Times(0); |
| OnSupplicantAppear(); |
| } |
| |
| TEST_F(WiFiMainTest, OnSupplicantVanishStarted) { |
| EXPECT_TRUE(GetSupplicantProcessProxy() == NULL); |
| |
| StartWiFi(); |
| EXPECT_FALSE(GetSupplicantProcessProxy() == NULL); |
| EXPECT_TRUE(GetSupplicantPresent()); |
| |
| EXPECT_CALL(*manager(), DeregisterDevice(_)); |
| EXPECT_CALL(*manager(), RegisterDevice(_)); |
| OnSupplicantVanish(); |
| } |
| |
| TEST_F(WiFiMainTest, OnSupplicantVanishStopped) { |
| OnSupplicantAppear(); |
| EXPECT_TRUE(GetSupplicantPresent()); |
| EXPECT_CALL(*manager(), DeregisterDevice(_)).Times(0); |
| OnSupplicantVanish(); |
| } |
| |
| TEST_F(WiFiMainTest, OnSupplicantVanishedWhileConnected) { |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| WiFiService *service(SetupConnectedService(DBus::Path())); |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(logging::LOG_INFO, _, |
| EndsWith("silently resetting current_service_."))); |
| EXPECT_CALL(*manager(), DeregisterDevice(_)) |
| .WillOnce(InvokeWithoutArgs(this, &WiFiObjectTest::StopWiFi)); |
| EXPECT_CALL(*manager(), DeregisterService(ServiceRefPtr(service))) |
| .WillOnce(Invoke(this, &WiFiObjectTest::UnloadService)); |
| EXPECT_CALL(supplicant_interface_proxy, Disconnect()).Times(0); |
| EXPECT_CALL(*manager(), RegisterDevice(_)); |
| OnSupplicantVanish(); |
| EXPECT_TRUE(GetCurrentService() == NULL); |
| } |
| |
| TEST_F(WiFiMainTest, CleanStart) { |
| EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_)); |
| EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_)) |
| .Times(AnyNumber()) |
| .WillRepeatedly(Throw( |
| DBus::Error( |
| "fi.w1.wpa_supplicant1.InterfaceUnknown", |
| "test threw fi.w1.wpa_supplicant1.InterfaceUnknown"))); |
| EXPECT_CALL(*supplicant_interface_proxy_, Scan(_)); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, Restart) { |
| EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_)) |
| .Times(AnyNumber()) |
| .WillRepeatedly(Throw( |
| DBus::Error( |
| "fi.w1.wpa_supplicant1.InterfaceExists", |
| "test threw fi.w1.wpa_supplicant1.InterfaceExists"))); |
| EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_)); |
| EXPECT_CALL(*supplicant_interface_proxy_, Scan(_)); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, StartClearsState) { |
| EXPECT_CALL(*supplicant_interface_proxy_, RemoveAllNetworks()); |
| EXPECT_CALL(*supplicant_interface_proxy_, FlushBSS(_)); |
| StartWiFi(); |
| } |
| |
| TEST_F(WiFiMainTest, ResumeStartsScanWhenIdle) { |
| EXPECT_CALL(*supplicant_interface_proxy_, Scan(_)); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_); |
| ReportScanDone(); |
| ASSERT_TRUE(wifi()->IsIdle()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| OnAfterResume(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, SuspendDoesNotStartScan) { |
| EXPECT_CALL(*supplicant_interface_proxy_, Scan(_)); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_); |
| ASSERT_TRUE(wifi()->IsIdle()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| OnBeforeSuspend(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ResumeDoesNotStartScanWhenNotIdle) { |
| EXPECT_CALL(*supplicant_interface_proxy_, Scan(_)); |
| StartWiFi(); |
| |
| WiFiEndpointRefPtr ap = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiServiceRefPtr service = CreateServiceForEndpoint(*ap); |
| Error error; |
| ScopedMockLog log; |
| service->AddEndpoint(ap); |
| service->AutoConnect(); |
| EXPECT_FALSE(wifi()->IsIdle()); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_); |
| ASSERT_FALSE(wifi()->IsIdle()); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, EndsWith("already scanning or connected."))); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| OnAfterResume(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ScanResults) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportBSS( |
| "bss1", "ssid1", "00:00:00:00:00:01", 1, 0, kNetworkModeInfrastructure); |
| ReportBSS( |
| "bss2", "ssid2", "00:00:00:00:00:02", 2, 0, kNetworkModeInfrastructure); |
| ReportBSS( |
| "bss3", "ssid3", "00:00:00:00:00:03", 3, 0, kNetworkModeInfrastructure); |
| const uint16 frequency = 2412; |
| ReportBSS("bss4", "ssid4", "00:00:00:00:00:04", 4, frequency, |
| kNetworkModeAdHoc); |
| |
| const WiFi::EndpointMap &endpoints_by_rpcid = GetEndpointMap(); |
| EXPECT_EQ(5, endpoints_by_rpcid.size()); |
| |
| WiFi::EndpointMap::const_iterator i; |
| WiFiEndpointRefPtr endpoint; |
| for (i = endpoints_by_rpcid.begin(); |
| i != endpoints_by_rpcid.end(); |
| ++i) { |
| if (i->second->bssid_string() == "00:00:00:00:00:04") |
| break; |
| } |
| ASSERT_TRUE(i != endpoints_by_rpcid.end()); |
| EXPECT_EQ(4, i->second->signal_strength()); |
| EXPECT_EQ(frequency, i->second->frequency()); |
| EXPECT_EQ("adhoc", i->second->network_mode()); |
| } |
| |
| TEST_F(WiFiMainTest, ScanResultsWithUpdates) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportBSS( |
| "bss1", "ssid1", "00:00:00:00:00:01", 1, 0, kNetworkModeInfrastructure); |
| ReportBSS( |
| "bss2", "ssid2", "00:00:00:00:00:02", 2, 0, kNetworkModeInfrastructure); |
| ReportBSS( |
| "bss1", "ssid1", "00:00:00:00:00:01", 3, 0, kNetworkModeInfrastructure); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 4, 0, kNetworkModeAdHoc); |
| |
| const WiFi::EndpointMap &endpoints_by_rpcid = GetEndpointMap(); |
| EXPECT_EQ(3, endpoints_by_rpcid.size()); |
| |
| WiFi::EndpointMap::const_iterator i; |
| WiFiEndpointRefPtr endpoint; |
| for (i = endpoints_by_rpcid.begin(); |
| i != endpoints_by_rpcid.end(); |
| ++i) { |
| if (i->second->bssid_string() == "00:00:00:00:00:00") |
| break; |
| } |
| ASSERT_TRUE(i != endpoints_by_rpcid.end()); |
| EXPECT_EQ(4, i->second->signal_strength()); |
| } |
| |
| TEST_F(WiFiMainTest, ScanCompleted) { |
| StartWiFi(); |
| EXPECT_CALL(*manager(), RegisterService(_)) |
| .Times(3); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportBSS( |
| "bss1", "ssid1", "00:00:00:00:00:01", 1, 0, kNetworkModeInfrastructure); |
| ReportBSS( |
| "bss2", "ssid2", "00:00:00:00:00:02", 2, 0, kNetworkModeInfrastructure); |
| ReportScanDone(); |
| EXPECT_EQ(3, GetServices().size()); |
| |
| // BSSes with SSIDs that start with NULL should be filtered. |
| ReportBSS("bss3", string(1, 0), "00:00:00:00:00:03", 3, 0, kNetworkModeAdHoc); |
| EXPECT_EQ(3, GetEndpointMap().size()); |
| EXPECT_EQ(3, GetServices().size()); |
| |
| // BSSes with empty SSIDs should be filtered. |
| ReportBSS("bss3", string(), "00:00:00:00:00:03", 3, 0, kNetworkModeAdHoc); |
| EXPECT_EQ(3, GetEndpointMap().size()); |
| EXPECT_EQ(3, GetServices().size()); |
| } |
| |
| TEST_F(WiFiMainTest, EndpointGroupingTogether) { |
| StartWiFi(); |
| |
| InSequence s; |
| EXPECT_CALL(*manager(), RegisterService(_)); |
| EXPECT_CALL(*manager(), HasService(_)); |
| EXPECT_CALL(*manager(), UpdateService(_)); |
| ReportBSS("bss0", "ssid", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportBSS("bss1", "ssid", "00:00:00:00:00:01", 0, 0, kNetworkModeAdHoc); |
| ReportScanDone(); |
| EXPECT_EQ(1, GetServices().size()); |
| } |
| |
| TEST_F(WiFiMainTest, EndpointGroupingDifferentSSID) { |
| StartWiFi(); |
| EXPECT_CALL(*manager(), RegisterService(_)) |
| .Times(2); |
| ReportBSS("bss0", "ssid1", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportBSS("bss1", "ssid2", "00:00:00:00:00:01", 0, 0, kNetworkModeAdHoc); |
| ReportScanDone(); |
| EXPECT_EQ(2, GetServices().size()); |
| } |
| |
| TEST_F(WiFiMainTest, EndpointGroupingDifferentMode) { |
| StartWiFi(); |
| EXPECT_CALL(*manager(), RegisterService(_)) |
| .Times(2); |
| ReportBSS("bss0", "ssid", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportBSS("bss1", "ssid", "00:00:00:00:00:01", 0, 0, |
| kNetworkModeInfrastructure); |
| ReportScanDone(); |
| EXPECT_EQ(2, GetServices().size()); |
| } |
| |
| TEST_F(WiFiMainTest, NonExistentBSSRemoved) { |
| // Removal of non-existent BSS should not cause a crash. |
| StartWiFi(); |
| RemoveBSS("bss0"); |
| EXPECT_EQ(0, GetServices().size()); |
| } |
| |
| TEST_F(WiFiMainTest, BSSWithEmptySSIDRemoved) { |
| // Removal of BSS with an empty SSID should not cause a crash. |
| ReportBSS("bss", string(), "00:00:00:00:00:01", 0, 0, kNetworkModeAdHoc); |
| StartWiFi(); |
| RemoveBSS("bss"); |
| EXPECT_EQ(0, GetServices().size()); |
| } |
| |
| TEST_F(WiFiMainTest, BSSWithNullSSIDRemoved) { |
| // Removal of BSS with a NULL SSID should not cause a crash. |
| ReportBSS("bss", string(1, 0), "00:00:00:00:00:01", 0, 0, kNetworkModeAdHoc); |
| StartWiFi(); |
| RemoveBSS("bss"); |
| EXPECT_EQ(0, GetServices().size()); |
| } |
| |
| TEST_F(WiFiMainTest, LoneBSSRemoved) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| StartWiFi(); |
| ReportBSS("bss0", "ssid", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportScanDone(); |
| EXPECT_EQ(1, GetServices().size()); |
| EXPECT_TRUE(GetServices().front()->IsVisible()); |
| |
| EXPECT_CALL(*manager(), DeregisterService(_)); |
| RemoveBSS("bss0"); |
| EXPECT_TRUE(GetServices().empty()); |
| } |
| |
| TEST_F(WiFiMainTest, LoneBSSRemovedWhileConnected) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| StartWiFi(); |
| ReportBSS("bss0", "ssid", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportScanDone(); |
| ReportCurrentBSSChanged("bss0"); |
| |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| EXPECT_CALL(*manager(), DeregisterService(_)); |
| RemoveBSS("bss0"); |
| EXPECT_TRUE(GetServices().empty()); |
| } |
| |
| TEST_F(WiFiMainTest, LoneBSSRemovedWhileConnectedToHidden) { |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber()); |
| StartWiFi(); |
| |
| Error e; |
| WiFiServiceRefPtr service = |
| GetServiceInner(flimflam::kTypeWifi, "ssid", flimflam::kModeManaged, |
| NULL, NULL, true, &e); |
| EXPECT_EQ(1, GetServices().size()); |
| |
| ReportBSS("bss", "ssid", "00:00:00:00:00:01", 0, 0, |
| kNetworkModeInfrastructure); |
| ReportScanDone(); |
| ReportCurrentBSSChanged("bss"); |
| EXPECT_EQ(1, GetServices().size()); |
| |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| RemoveBSS("bss"); |
| EXPECT_EQ(1, GetServices().size()); |
| // Verify expectations now, because WiFi may call UpdateService when |
| // WiFi is Stop()-ed (during TearDown()). |
| Mock::VerifyAndClearExpectations(manager()); |
| EXPECT_CALL(*manager(), DeregisterService(_)).Times(AnyNumber()); |
| } |
| |
| TEST_F(WiFiMainTest, NonSolitaryBSSRemoved) { |
| EXPECT_CALL(*manager(), RegisterService(_)); |
| EXPECT_CALL(*manager(), HasService(_)); |
| EXPECT_CALL(*manager(), UpdateService(_)); |
| StartWiFi(); |
| ReportBSS("bss0", "ssid", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportBSS("bss1", "ssid", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportScanDone(); |
| EXPECT_EQ(1, GetServices().size()); |
| EXPECT_TRUE(GetServices().front()->IsVisible()); |
| |
| EXPECT_CALL(*manager(), UpdateService(_)); |
| RemoveBSS("bss0"); |
| EXPECT_TRUE(GetServices().front()->IsVisible()); |
| EXPECT_EQ(1, GetServices().size()); |
| } |
| |
| TEST_F(WiFiMainTest, Connect) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportScanDone(); |
| |
| { |
| InSequence s; |
| DBus::Path fake_path("/fake/path"); |
| WiFiService *service(GetServices().begin()->get()); |
| |
| EXPECT_CALL(supplicant_interface_proxy, AddNetwork(_)) |
| .WillOnce(Return(fake_path)); |
| EXPECT_CALL(supplicant_interface_proxy, SelectNetwork(fake_path)); |
| InitiateConnect(service); |
| EXPECT_EQ(static_cast<Service *>(service), |
| wifi()->selected_service_.get()); |
| EXPECT_EQ(Service::kStateAssociating, service->state()); |
| EXPECT_FALSE(GetPendingTimeout().IsCancelled()); |
| } |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectPendingService) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| WiFiService *service(GetServices().begin()->get()); |
| InitiateConnect(service); |
| |
| EXPECT_FALSE(GetPendingService() == NULL); |
| EXPECT_TRUE(service->IsConnecting()); |
| EXPECT_CALL(supplicant_interface_proxy, Disconnect()); |
| InitiateDisconnect(service); |
| EXPECT_FALSE(service->IsConnecting()); |
| |
| EXPECT_TRUE(GetPendingService() == NULL); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectPendingServiceWithCurrent) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportBSS("bss1", "ssid1", "00:00:00:00:00:01", 0, 0, kNetworkModeAdHoc); |
| WiFiService *service0(GetServices()[0].get()); |
| WiFiService *service1(GetServices()[1].get()); |
| |
| InitiateConnect(service0); |
| ReportCurrentBSSChanged("bss0"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| InitiateConnect(service1); |
| |
| EXPECT_EQ(service0, GetCurrentService()); |
| EXPECT_EQ(service1, GetPendingService()); |
| EXPECT_CALL(supplicant_interface_proxy, Disconnect()); |
| InitiateDisconnect(service1); |
| |
| // |current_service_| will be unchanged until supplicant signals |
| // that CurrentBSS has changed. |
| EXPECT_EQ(service0, GetCurrentService()); |
| // |pending_service_| is updated immediately. |
| EXPECT_TRUE(GetPendingService() == NULL); |
| EXPECT_TRUE(GetPendingTimeout().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectCurrentService) { |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| WiFiService *service(SetupConnectedService(DBus::Path())); |
| EXPECT_CALL(supplicant_interface_proxy, Disconnect()); |
| InitiateDisconnect(service); |
| |
| // |current_service_| should not change until supplicant reports |
| // a BSS change. |
| EXPECT_EQ(service, GetCurrentService()); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectCurrentServiceWithPending) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportBSS("bss1", "ssid1", "00:00:00:00:00:01", 0, 0, kNetworkModeAdHoc); |
| WiFiService *service0(GetServices()[0].get()); |
| WiFiService *service1(GetServices()[1].get()); |
| |
| InitiateConnect(service0); |
| ReportCurrentBSSChanged("bss0"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| InitiateConnect(service1); |
| |
| EXPECT_EQ(service0, GetCurrentService()); |
| EXPECT_EQ(service1, GetPendingService()); |
| EXPECT_CALL(supplicant_interface_proxy, Disconnect()) |
| .Times(0); |
| InitiateDisconnect(service0); |
| |
| EXPECT_EQ(service0, GetCurrentService()); |
| EXPECT_EQ(service1, GetPendingService()); |
| EXPECT_FALSE(GetPendingTimeout().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, TimeoutPendingService) { |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| const base::CancelableClosure &pending_timeout = GetPendingTimeout(); |
| EXPECT_TRUE(pending_timeout.IsCancelled()); |
| |
| InSequence seq; |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| EXPECT_CALL(*service, SetState(Service::kStateAssociating)); |
| InitiateConnect(service); |
| EXPECT_FALSE(pending_timeout.IsCancelled()); |
| EXPECT_EQ(service, GetPendingService()); |
| |
| { |
| InSequence seq; |
| EXPECT_CALL(*service, SetState(Service::kStateIdle)); |
| EXPECT_CALL(*service, SetFailure(Service::kFailureOutOfRange)); |
| pending_timeout.callback().Run(); |
| } |
| EXPECT_EQ(NULL, GetPendingService().get()); |
| |
| // Verify expectations now, because WiFi may report other state changes |
| // when WiFi is Stop()-ed (during TearDown()). |
| Mock::VerifyAndClearExpectations(service.get()); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectInvalidService) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| WiFiService *service(GetServices().begin()->get()); |
| EXPECT_CALL(supplicant_interface_proxy, Disconnect()) |
| .Times(0); |
| InitiateDisconnect(service); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectCurrentServiceFailure) { |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| DBus::Path fake_path("/fake/path"); |
| WiFiService *service(SetupConnectedService(fake_path)); |
| EXPECT_CALL(supplicant_interface_proxy, Disconnect()) |
| .WillRepeatedly(Throw( |
| DBus::Error( |
| "fi.w1.wpa_supplicant1.NotConnected", |
| "test threw fi.w1.wpa_supplicant1.NotConnected"))); |
| EXPECT_CALL(supplicant_interface_proxy, RemoveNetwork(fake_path)); |
| InitiateDisconnect(service); |
| |
| EXPECT_TRUE(GetCurrentService() == NULL); |
| } |
| |
| TEST_F(WiFiMainTest, Stop) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportScanDone(); |
| |
| EXPECT_CALL(*manager(), DeregisterService(_)); |
| StopWiFi(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| EXPECT_FALSE(wifi()->weak_ptr_factory_.HasWeakPtrs()); |
| } |
| |
| TEST_F(WiFiMainTest, StopWhileConnected) { |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| WiFiService *service(SetupConnectedService(DBus::Path())); |
| EXPECT_CALL(*manager(), DeregisterService(ServiceRefPtr(service))) |
| .WillOnce(Invoke(this, &WiFiObjectTest::UnloadService)); |
| EXPECT_CALL(supplicant_interface_proxy, Disconnect()); |
| StopWiFi(); |
| EXPECT_TRUE(GetCurrentService() == NULL); |
| } |
| |
| TEST_F(WiFiMainTest, ReconnectTimer) { |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| WiFiService *service(SetupConnectedService(DBus::Path())); |
| service->SetState(Service::kStateConnected); |
| EXPECT_TRUE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateDisconnected); |
| EXPECT_FALSE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| EXPECT_TRUE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateDisconnected); |
| EXPECT_FALSE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportCurrentBSSChanged(kBSSName); |
| EXPECT_TRUE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateDisconnected); |
| EXPECT_FALSE(GetReconnectTimeoutCallback().IsCancelled()); |
| EXPECT_CALL(supplicant_interface_proxy, Disconnect()); |
| GetReconnectTimeoutCallback().callback().Run(); |
| Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_); |
| EXPECT_TRUE(GetReconnectTimeoutCallback().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceOpen) { |
| Error e; |
| GetOpenService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceOpenNoSSID) { |
| Error e; |
| GetOpenService(flimflam::kTypeWifi, NULL, flimflam::kModeManaged, &e); |
| EXPECT_EQ(Error::kInvalidArguments, e.type()); |
| EXPECT_EQ("must specify SSID", e.message()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceOpenLongSSID) { |
| Error e; |
| GetOpenService( |
| flimflam::kTypeWifi, "123456789012345678901234567890123", |
| flimflam::kModeManaged, &e); |
| EXPECT_EQ(Error::kInvalidNetworkName, e.type()); |
| EXPECT_EQ("SSID is too long", e.message()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceOpenShortSSID) { |
| Error e; |
| GetOpenService(flimflam::kTypeWifi, "", flimflam::kModeManaged, &e); |
| EXPECT_EQ(Error::kInvalidNetworkName, e.type()); |
| EXPECT_EQ("SSID is too short", e.message()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceOpenBadMode) { |
| Error e; |
| GetOpenService(flimflam::kTypeWifi, "an_ssid", "ad-hoc", &e); |
| EXPECT_EQ(Error::kNotSupported, e.type()); |
| EXPECT_EQ("service mode is unsupported", e.message()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceOpenNoMode) { |
| Error e; |
| GetOpenService(flimflam::kTypeWifi, "an_ssid", NULL, &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceRSN) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityRsn, "secure password", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceRSNNoPassword) { |
| // When configuring hidden networks, Chrome expects to be able to |
| // GetService w/o a password, and supply the password with |
| // SetProperty afterwards. |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityRsn, NULL, &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceBadSecurity) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, "rot-13", |
| NULL, &e); |
| EXPECT_EQ(Error::kNotSupported, e.type()); |
| EXPECT_EQ("security mode is unsupported", e.message()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEPNoPassword) { |
| // When configuring hidden networks, Chrome expects to be able to |
| // GetService w/o a password, and supply the password with |
| // SetProperty afterwards. |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, NULL, &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEPEmptyPassword) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "", &e); |
| EXPECT_EQ(Error::kInvalidPassphrase, e.type()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP40ASCII) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "abcde", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP104ASCII) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "abcdefghijklm", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP40ASCIIWithKeyIndex) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "0:abcdefghijklm", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP40Hex) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "0102030405", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP40HexBadPassphrase) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "O102030405", &e); |
| EXPECT_EQ(Error::kInvalidPassphrase, e.type()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP40HexWithKeyIndexBadPassphrase) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "1:O102030405", &e); |
| EXPECT_EQ(Error::kInvalidPassphrase, e.type()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP40HexWithKeyIndexAndBaseBadPassphrase) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "1:0xO102030405", &e); |
| EXPECT_EQ(Error::kInvalidPassphrase, e.type()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP40HexWithBaseBadPassphrase) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "0xO102030405", &e); |
| EXPECT_EQ(Error::kInvalidPassphrase, e.type()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP104Hex) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "0102030405060708090a0b0c0d", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP104HexUppercase) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "0102030405060708090A0B0C0D", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP104HexWithKeyIndex) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "0:0102030405060708090a0b0c0d", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_F(WiFiMainTest, GetWifiServiceWEP104HexWithKeyIndexAndBase) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWep, "0:0x0102030405060708090a0b0c0d", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| class WiFiGetServiceSuccessTest : public WiFiMainTest {}; |
| class WiFiGetServiceFailureTest : public WiFiMainTest {}; |
| |
| TEST_P(WiFiGetServiceSuccessTest, Passphrase) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWpa, GetParam().c_str(), &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| |
| TEST_P(WiFiGetServiceFailureTest, Passphrase) { |
| Error e; |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWpa, GetParam().c_str(), &e); |
| EXPECT_EQ(Error::kInvalidPassphrase, e.type()); |
| } |
| |
| INSTANTIATE_TEST_CASE_P( |
| WiFiGetServiceSuccessTestInstance, |
| WiFiGetServiceSuccessTest, |
| Values( |
| string(IEEE_80211::kWPAAsciiMinLen, 'Z'), |
| string(IEEE_80211::kWPAAsciiMaxLen, 'Z'), |
| // subtle: invalid length for hex key, but valid as ascii passphrase |
| string(IEEE_80211::kWPAHexLen-1, '1'), |
| string(IEEE_80211::kWPAHexLen, '1'))); |
| |
| INSTANTIATE_TEST_CASE_P( |
| WiFiGetServiceFailureTestInstance, |
| WiFiGetServiceFailureTest, |
| Values( |
| string(IEEE_80211::kWPAAsciiMinLen-1, 'Z'), |
| string(IEEE_80211::kWPAAsciiMaxLen+1, 'Z'), |
| string(IEEE_80211::kWPAHexLen+1, '1'))); |
| |
| TEST_F(WiFiMainTest, FindServiceWEP) { |
| const string ssid("an_ssid"); |
| { |
| Error e; |
| GetService(flimflam::kTypeWifi, ssid.c_str(), flimflam::kModeManaged, |
| flimflam::kSecurityWep, "abcde", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| vector<uint8_t> ssid_bytes(ssid.begin(), ssid.end()); |
| |
| EXPECT_TRUE(FindService(ssid_bytes, flimflam::kModeManaged, |
| flimflam::kSecurityWep).get()); |
| EXPECT_FALSE(FindService(ssid_bytes, flimflam::kModeManaged, |
| flimflam::kSecurityWpa).get()); |
| } |
| |
| TEST_F(WiFiMainTest, FindServiceWPA) { |
| const string ssid("an_ssid"); |
| { |
| Error e; |
| GetService(flimflam::kTypeWifi, ssid.c_str(), flimflam::kModeManaged, |
| flimflam::kSecurityRsn, "abcdefgh", &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| } |
| vector<uint8_t> ssid_bytes(ssid.begin(), ssid.end()); |
| WiFiServiceRefPtr wpa_service(FindService(ssid_bytes, flimflam::kModeManaged, |
| flimflam::kSecurityWpa)); |
| EXPECT_TRUE(wpa_service.get()); |
| WiFiServiceRefPtr rsn_service(FindService(ssid_bytes, flimflam::kModeManaged, |
| flimflam::kSecurityRsn)); |
| EXPECT_TRUE(rsn_service.get()); |
| EXPECT_EQ(wpa_service.get(), rsn_service.get()); |
| WiFiServiceRefPtr psk_service(FindService(ssid_bytes, flimflam::kModeManaged, |
| flimflam::kSecurityPsk)); |
| EXPECT_EQ(wpa_service.get(), psk_service.get()); |
| // Indirectly test FindService by doing a GetService on something that |
| // already exists. |
| { |
| Error e; |
| WiFiServiceRefPtr wpa_service2( |
| GetServiceInner(flimflam::kTypeWifi, ssid.c_str(), |
| flimflam::kModeManaged, flimflam::kSecurityWpa, |
| "abcdefgh", false, &e)); |
| EXPECT_TRUE(e.IsSuccess()); |
| EXPECT_EQ(wpa_service.get(), wpa_service2.get()); |
| } |
| } |
| |
| TEST_F(WiFiMainTest, GetServiceWithGUID) { |
| // Perform a GetService that also configures properties in the base Service |
| // class using Service::Configure(). |
| KeyValueStore args; |
| args.SetString(flimflam::kTypeProperty, flimflam::kTypeWifi); |
| args.SetString(flimflam::kSSIDProperty, "ssid"); |
| args.SetString(flimflam::kSecurityProperty, flimflam::kSecurityNone); |
| const string kGUID = "aguid"; // Stored as a registered Service property. |
| args.SetString(flimflam::kGuidProperty, kGUID); |
| Error e; |
| WiFiServiceRefPtr service = GetServiceWithKeyValues(args, &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| EXPECT_EQ(kGUID, service->guid()); |
| } |
| |
| MATCHER_P(HasHiddenSSID, ssid, "") { |
| map<string, DBus::Variant>::const_iterator it = |
| arg.find(wpa_supplicant::kPropertyScanSSIDs); |
| if (it == arg.end()) { |
| return false; |
| } |
| |
| const DBus::Variant &ssids_variant = it->second; |
| EXPECT_TRUE(DBusAdaptor::IsByteArrays(ssids_variant.signature())); |
| const ByteArrays &ssids = it->second.operator ByteArrays(); |
| // A valid Scan containing a single hidden SSID should contain |
| // two SSID entries: one containing the SSID we are looking for, |
| // and an empty entry, signifying that we also want to do a |
| // broadcast probe request for all non-hidden APs as well. |
| return ssids.size() == 2 && |
| string(ssids[0].begin(), ssids[0].end()) == ssid && |
| ssids[1].empty(); |
| } |
| |
| TEST_F(WiFiMainTest, ScanHidden) { |
| EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_)); |
| EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_)) |
| .Times(AnyNumber()) |
| .WillRepeatedly(Throw( |
| DBus::Error( |
| "fi.w1.wpa_supplicant1.InterfaceUnknown", |
| "test threw fi.w1.wpa_supplicant1.InterfaceUnknown"))); |
| scoped_refptr<MockProfile> profile( |
| new NiceMock<MockProfile>(control_interface(), manager(), "")); |
| { |
| // Create a hidden service with an associated profile. |
| Error e; |
| WiFiServiceRefPtr service = |
| GetServiceInner(flimflam::kTypeWifi, "ssid0", flimflam::kModeManaged, |
| NULL, NULL, true, &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| EXPECT_TRUE(service->hidden_ssid()); |
| service->set_profile(profile); |
| } |
| { |
| // Create a hidden service without an associated profile. |
| Error e; |
| WiFiServiceRefPtr service = |
| GetServiceInner(flimflam::kTypeWifi, "ssid1", flimflam::kModeManaged, |
| NULL, NULL, true, &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| EXPECT_TRUE(service->hidden_ssid()); |
| } |
| { |
| // Create a non-hidden service with an associated profile. |
| Error e; |
| WiFiServiceRefPtr service = |
| GetServiceInner(flimflam::kTypeWifi, "ssid2", flimflam::kModeManaged, |
| NULL, NULL, false, &e); |
| EXPECT_TRUE(e.IsSuccess()); |
| EXPECT_FALSE(service->hidden_ssid()); |
| service->set_profile(profile); |
| } |
| EXPECT_CALL(*supplicant_interface_proxy_, Scan(HasHiddenSSID("ssid0"))); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ScanWiFiDisabledAfterResume) { |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, EndsWith( |
| "Ignoring scan request while device is not enabled."))).Times(1); |
| EXPECT_CALL(*supplicant_interface_proxy_, Scan(_)).Times(0); |
| StartWiFi(); |
| StopWiFi(); |
| // A scan is queued when WiFi resumes. |
| OnAfterResume(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, InitialSupplicantState) { |
| EXPECT_EQ(WiFi::kInterfaceStateUnknown, GetSupplicantState()); |
| } |
| |
| TEST_F(WiFiMainTest, StateChangeNoService) { |
| // State change should succeed even if there is no pending Service. |
| ReportStateChanged(wpa_supplicant::kInterfaceStateScanning); |
| EXPECT_EQ(wpa_supplicant::kInterfaceStateScanning, GetSupplicantState()); |
| } |
| |
| TEST_F(WiFiMainTest, StateChangeWithService) { |
| // Forward transition should trigger a Service state change. |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| InitiateConnect(service); |
| EXPECT_CALL(*service.get(), SetState(Service::kStateAssociating)); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateAssociated); |
| // Verify expectations now, because WiFi may report other state changes |
| // when WiFi is Stop()-ed (during TearDown()). |
| Mock::VerifyAndClearExpectations(service.get()); |
| EXPECT_CALL(*service.get(), SetState(_)).Times(AnyNumber()); |
| } |
| |
| TEST_F(WiFiMainTest, StateChangeBackwardsWithService) { |
| // Some backwards transitions should not trigger a Service state change. |
| // Supplicant state should still be updated, however. |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber()); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| EXPECT_CALL(*service.get(), SetState(Service::kStateAssociating)); |
| EXPECT_CALL(*service.get(), SetState(Service::kStateConfiguring)); |
| InitiateConnect(service); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateAuthenticating); |
| EXPECT_EQ(wpa_supplicant::kInterfaceStateAuthenticating, |
| GetSupplicantState()); |
| // Verify expectations now, because WiFi may report other state changes |
| // when WiFi is Stop()-ed (during TearDown()). |
| Mock::VerifyAndClearExpectations(service.get()); |
| EXPECT_CALL(*service.get(), SetState(_)).Times(AnyNumber()); |
| } |
| |
| TEST_F(WiFiMainTest, LoadHiddenServicesFailWithNoGroups) { |
| StrictMock<MockStore> storage; |
| EXPECT_CALL(storage, GetGroupsWithKey(flimflam::kWifiHiddenSsid)) |
| .WillOnce(Return(set<string>())); |
| EXPECT_FALSE(LoadHiddenServices(&storage)); |
| } |
| |
| TEST_F(WiFiMainTest, LoadHiddenServicesFailWithMissingHidden) { |
| string id; |
| StrictMock<MockStore> storage; |
| SetupHiddenStorage(&storage, "an_ssid", &id); |
| // Missing "Hidden" property. |
| EXPECT_CALL(storage, GetBool(StrEq(id), flimflam::kWifiHiddenSsid, _)) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(LoadHiddenServices(&storage)); |
| } |
| |
| TEST_F(WiFiMainTest, LoadHiddenServicesFailWithFalseHidden) { |
| string id; |
| StrictMock<MockStore> storage; |
| SetupHiddenStorage(&storage, "an_ssid", &id); |
| // "Hidden" property set to "false". |
| EXPECT_CALL(storage, GetBool(StrEq(id), flimflam::kWifiHiddenSsid, _)) |
| .WillOnce(DoAll(SetArgumentPointee<2>(true), Return(false))); |
| EXPECT_FALSE(LoadHiddenServices(&storage)); |
| } |
| |
| TEST_F(WiFiMainTest, LoadHiddenServicesFailWithMissingSSID) { |
| string id; |
| StrictMock<MockStore> storage; |
| SetupHiddenStorage(&storage, "an_ssid", &id); |
| // Missing "SSID" property. |
| EXPECT_CALL(storage, GetString(StrEq(id), flimflam::kSSIDProperty, _)) |
| .WillOnce(Return(false)); |
| EXPECT_FALSE(LoadHiddenServices(&storage)); |
| } |
| |
| |
| TEST_F(WiFiMainTest, LoadHiddenServicesFailWithFoundService) { |
| StrictMock<MockStore> storage; |
| string id; |
| SetupHiddenStorage(&storage, "an_ssid", &id); |
| Error e; |
| GetOpenService(flimflam::kTypeWifi, "an_ssid", NULL, &e); |
| ASSERT_TRUE(e.IsSuccess()); |
| EXPECT_FALSE(LoadHiddenServices(&storage)); |
| } |
| |
| TEST_F(WiFiMainTest, LoadHiddenServicesSuccess) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| StrictMock<MockStore> storage; |
| string ssid("an_ssid"); |
| string id; |
| SetupHiddenStorage(&storage, ssid, &id); |
| EXPECT_TRUE(LoadHiddenServices(&storage)); |
| vector<uint8_t> ssid_bytes(ssid.begin(), ssid.end()); |
| EXPECT_TRUE(FindService(ssid_bytes, flimflam::kModeManaged, |
| flimflam::kSecurityNone).get()); |
| } |
| |
| TEST_F(WiFiMainTest, CurrentBSSChangeConnectedToDisconnected) { |
| EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| WiFiEndpointRefPtr ap = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiServiceRefPtr service = CreateServiceForEndpoint(*ap); |
| |
| // Note that the BSS handle used in this test ("an_ap") is not |
| // intended to reflect the format used by supplicant. It's just |
| // convenient for testing. |
| |
| StartWiFi(); |
| ReportBSS("an_ap", ap->ssid_string(), ap->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| InitiateConnect(service); |
| EXPECT_EQ(service, GetPendingService().get()); |
| |
| ReportCurrentBSSChanged("an_ap"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| EXPECT_EQ(Service::kStateConfiguring, service->state()); |
| EXPECT_EQ(service, GetCurrentService().get()); |
| EXPECT_EQ(NULL, GetPendingService().get()); |
| |
| ReportCurrentBSSChanged(wpa_supplicant::kCurrentBSSNull); |
| EXPECT_EQ(Service::kStateIdle, service->state()); |
| EXPECT_TRUE(service->IsFailed()); |
| EXPECT_EQ(NULL, GetCurrentService().get()); |
| EXPECT_EQ(NULL, GetPendingService().get()); |
| } |
| |
| TEST_F(WiFiMainTest, CurrentBSSChangeConnectedToConnectedNewService) { |
| EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| WiFiEndpointRefPtr ap1 = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiEndpointRefPtr ap2 = MakeEndpoint("another_ssid", "01:02:03:04:05:06"); |
| WiFiServiceRefPtr service1 = CreateServiceForEndpoint(*ap1); |
| WiFiServiceRefPtr service2 = CreateServiceForEndpoint(*ap2); |
| |
| // Note that the BSS handles used in this test ("ap1", "ap2") are |
| // not intended to reflect the format used by supplicant. They're |
| // just convenient for testing. |
| |
| StartWiFi(); |
| ReportBSS("ap1", ap1->ssid_string(), ap1->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| ReportBSS("ap2", ap2->ssid_string(), ap2->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| InitiateConnect(service1); |
| ReportCurrentBSSChanged("ap1"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| EXPECT_EQ(service1.get(), GetCurrentService().get()); |
| |
| // Note that we deliberately omit intermediate supplicant states |
| // (e.g. kInterfaceStateAssociating), on the theory that they are |
| // unreliable. Specifically, they may be quashed if the association |
| // completes before supplicant flushes its changed properties. |
| ReportCurrentBSSChanged("ap2"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| EXPECT_EQ(service2.get(), GetCurrentService().get()); |
| EXPECT_EQ(Service::kStateIdle, service1->state()); |
| EXPECT_EQ(Service::kStateConfiguring, service2->state()); |
| } |
| |
| TEST_F(WiFiMainTest, CurrentBSSChangeDisconnectedToConnected) { |
| EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber()); |
| WiFiEndpointRefPtr ap = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiServiceRefPtr service = CreateServiceForEndpoint(*ap); |
| |
| // Note that the BSS handle used in this test ("an_ap") is not |
| // intended to reflect the format used by supplicant. It's just |
| // convenient for testing. |
| |
| StartWiFi(); |
| ReportBSS("an_ap", ap->ssid_string(), ap->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| InitiateConnect(service); |
| ReportCurrentBSSChanged("an_ap"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| EXPECT_EQ(service.get(), GetCurrentService().get()); |
| EXPECT_EQ(Service::kStateConfiguring, service->state()); |
| } |
| |
| TEST_F(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| |
| const uint16 frequency1 = 2412; |
| const uint16 frequency2 = 2442; |
| StartWiFi(); |
| ReportBSS("bss1", "ssid1", "00:00:00:00:00:01", 1, frequency1, |
| kNetworkModeInfrastructure); |
| ReportBSS("bss2", "ssid1", "00:00:00:00:00:02", 1, frequency2, |
| kNetworkModeInfrastructure); |
| EXPECT_EQ(1, GetServices().size()); |
| WiFiService *service(GetServices()[0].get()); |
| InitiateConnect(service); |
| ReportCurrentBSSChanged("bss1"); |
| EXPECT_EQ(frequency1, service->frequency_); |
| EXPECT_EQ("00:00:00:00:00:01", service->bssid_); |
| ReportCurrentBSSChanged("bss2"); |
| EXPECT_EQ(frequency2, service->frequency_); |
| EXPECT_EQ("00:00:00:00:00:02", service->bssid_); |
| } |
| |
| TEST_F(WiFiMainTest, ConfiguredServiceRegistration) { |
| Error e; |
| EXPECT_CALL(*manager(), RegisterService(_)) |
| .Times(0); |
| EXPECT_CALL(*manager(), HasService(_)) |
| .WillOnce(Return(false)); |
| GetOpenService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, &e); |
| EXPECT_CALL(*manager(), RegisterService(_)); |
| ReportBSS("ap0", "an_ssid", "00:00:00:00:00:00", 0, 0, |
| kNetworkModeInfrastructure); |
| } |
| |
| TEST_F(WiFiMainTest, NewConnectPreemptsPending) { |
| EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| WiFiEndpointRefPtr ap1 = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiEndpointRefPtr ap2 = MakeEndpoint("another_ssid", "01:02:03:04:05:06"); |
| WiFiServiceRefPtr service1 = CreateServiceForEndpoint(*ap1); |
| WiFiServiceRefPtr service2 = CreateServiceForEndpoint(*ap2); |
| |
| StartWiFi(); |
| ReportBSS("ap1", ap1->ssid_string(), ap1->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| ReportBSS("ap2", ap2->ssid_string(), ap2->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| InitiateConnect(service1); |
| EXPECT_EQ(service1.get(), GetPendingService().get()); |
| |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), AddNetwork(_)); |
| InitiateConnect(service2); |
| EXPECT_EQ(service2.get(), GetPendingService().get()); |
| } |
| |
| TEST_F(WiFiMainTest, IsIdle) { |
| StartWiFi(); |
| EXPECT_TRUE(wifi()->IsIdle()); |
| |
| WiFiEndpointRefPtr ap = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiServiceRefPtr service = CreateServiceForEndpoint(*ap); |
| Error error; |
| service->AddEndpoint(ap); |
| service->AutoConnect(); |
| EXPECT_FALSE(wifi()->IsIdle()); |
| } |
| |
| MATCHER_P(WiFiAddedArgs, bgscan, "") { |
| return ContainsKey(arg, wpa_supplicant::kNetworkPropertyScanSSID) && |
| ContainsKey(arg, wpa_supplicant::kNetworkPropertyBgscan) == bgscan; |
| } |
| |
| TEST_F(WiFiMainTest, AddNetworkArgs) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| WiFiService *service(GetServices().begin()->get()); |
| EXPECT_CALL(supplicant_interface_proxy, AddNetwork(WiFiAddedArgs(true))); |
| EXPECT_TRUE(SetBgscanMethod(wpa_supplicant::kNetworkBgscanMethodSimple)); |
| InitiateConnect(service); |
| } |
| |
| TEST_F(WiFiMainTest, AddNetworkArgsNoBgscan) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| WiFiService *service(GetServices().begin()->get()); |
| EXPECT_CALL(supplicant_interface_proxy, AddNetwork(WiFiAddedArgs(false))); |
| InitiateConnect(service); |
| } |
| |
| TEST_F(WiFiMainTest, AppendBgscan) { |
| StartWiFi(); |
| WiFiEndpointRefPtr ap1 = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiServiceRefPtr service = CreateServiceForEndpoint(*ap1); |
| service->AddEndpoint(ap1); |
| EXPECT_EQ(1, service->GetEndpointCount()); |
| { |
| // 1 endpoint, default bgscan method -- background scan disabled. |
| std::map<std::string, DBus::Variant> params; |
| AppendBgscan(service.get(), ¶ms); |
| EXPECT_FALSE(ContainsKey(params, wpa_supplicant::kNetworkPropertyBgscan)); |
| } |
| WiFiEndpointRefPtr ap2 = MakeEndpoint("an_ssid", "01:02:03:04:05:06"); |
| service->AddEndpoint(ap2); |
| EXPECT_EQ(2, service->GetEndpointCount()); |
| { |
| // 2 endpoints, default bgscan method -- background scan frequency reduced. |
| map<string, DBus::Variant> params; |
| AppendBgscan(service.get(), ¶ms); |
| string config_string; |
| EXPECT_TRUE( |
| DBusProperties::GetString(params, |
| wpa_supplicant::kNetworkPropertyBgscan, |
| &config_string)); |
| vector<string> elements; |
| base::SplitString(config_string, ':', &elements); |
| ASSERT_EQ(4, elements.size()); |
| EXPECT_EQ(WiFi::kDefaultBgscanMethod, elements[0]); |
| EXPECT_EQ(StringPrintf("%d", WiFi::kBackgroundScanIntervalSeconds), |
| elements[3]); |
| } |
| { |
| // Explicit bgscan method -- regular background scan frequency. |
| EXPECT_TRUE(SetBgscanMethod(wpa_supplicant::kNetworkBgscanMethodSimple)); |
| std::map<std::string, DBus::Variant> params; |
| AppendBgscan(service.get(), ¶ms); |
| string config_string; |
| EXPECT_TRUE( |
| DBusProperties::GetString(params, |
| wpa_supplicant::kNetworkPropertyBgscan, |
| &config_string)); |
| vector<string> elements; |
| base::SplitString(config_string, ':', &elements); |
| ASSERT_EQ(4, elements.size()); |
| EXPECT_EQ(StringPrintf("%d", WiFi::kDefaultScanIntervalSeconds), |
| elements[3]); |
| } |
| { |
| // No scan method, simply returns without appending properties |
| EXPECT_TRUE(SetBgscanMethod(wpa_supplicant::kNetworkBgscanMethodNone)); |
| std::map<std::string, DBus::Variant> params; |
| AppendBgscan(service.get(), ¶ms); |
| string config_string; |
| EXPECT_FALSE( |
| DBusProperties::GetString(params, |
| wpa_supplicant::kNetworkPropertyBgscan, |
| &config_string)); |
| } |
| } |
| |
| TEST_F(WiFiMainTest, StateAndIPIgnoreLinkEvent) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| InitiateConnect(service); |
| EXPECT_CALL(*service.get(), SetState(_)).Times(0); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(0); |
| ReportLinkUp(); |
| |
| // Verify expectations now, because WiFi may cause |service| state |
| // changes during TearDown(). |
| Mock::VerifyAndClearExpectations(service); |
| EXPECT_CALL(*service.get(), SetState(_)).Times(AnyNumber()); |
| } |
| |
| TEST_F(WiFiMainTest, SupplicantCompleted) { |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber()); |
| WiFiEndpointRefPtr ap = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiServiceRefPtr service = CreateServiceForEndpoint(*ap); |
| |
| StartWiFi(); |
| ReportBSS("ap", ap->ssid_string(), ap->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| InitiateConnect(service); |
| |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()); |
| ReportCurrentBSSChanged("ap"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| EXPECT_EQ(Service::kStateConfiguring, service->state()); |
| } |
| |
| TEST_F(WiFiMainTest, SupplicantCompletedAlreadyConnected) { |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()); |
| EXPECT_CALL(*manager(), UpdateService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*device_info(), FlushAddresses(_)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), device_info()).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), HasService(_)).Times(AnyNumber()); |
| EXPECT_CALL(*manager(), IsPortalDetectionEnabled(_)).Times(AnyNumber()); |
| WiFiEndpointRefPtr ap = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiServiceRefPtr service = CreateServiceForEndpoint(*ap); |
| |
| StartWiFi(); |
| ReportBSS("ap", ap->ssid_string(), ap->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| InitiateConnect(service); |
| ReportCurrentBSSChanged("ap"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| ReportIPConfigComplete(); |
| Mock::VerifyAndClearExpectations(service); |
| |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(0); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| } |
| |
| TEST_F(WiFiMainTest, ClearCachedCredentials) { |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| |
| StartWiFi(); |
| |
| // Ensure call to the proxy is deferred. |
| EXPECT_CALL(supplicant_interface_proxy, ClearCachedCredentials()) |
| .Times(0); |
| ClearCachedCredentials(); |
| |
| Mock::VerifyAndClearExpectations(&supplicant_interface_proxy); |
| |
| EXPECT_CALL(supplicant_interface_proxy, ClearCachedCredentials()) |
| .Times(1); |
| dispatcher_.DispatchPendingEvents(); |
| |
| Mock::VerifyAndClearExpectations(&supplicant_interface_proxy); |
| |
| EXPECT_CALL(supplicant_interface_proxy, ClearCachedCredentials()) |
| .Times(0); |
| ClearCachedCredentials(); |
| ClearCachedCredentials(); |
| |
| Mock::VerifyAndClearExpectations(&supplicant_interface_proxy); |
| |
| // Ensure multiple calls to ClearCachedCredentials() results in only |
| // one call to the proxy. |
| EXPECT_CALL(supplicant_interface_proxy, ClearCachedCredentials()) |
| .Times(1); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, BSSAddedCreatesBSSProxy) { |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| // TODO(quiche): Consider using a factory for WiFiEndpoints, so that |
| // we can test the interaction between WiFi and WiFiEndpoint. (Right |
| // now, we're testing across multiple layers.) |
| EXPECT_CALL(*supplicant_bss_proxy_, Die()).Times(AnyNumber()); |
| EXPECT_CALL(*proxy_factory(), CreateSupplicantBSSProxy(_, _, _)); |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| } |
| |
| TEST_F(WiFiMainTest, BSSRemovedDestroysBSSProxy) { |
| // TODO(quiche): As for BSSAddedCreatesBSSProxy, consider using a |
| // factory for WiFiEndpoints. |
| EXPECT_CALL(*manager(), RegisterService(_)).Times(AnyNumber()); |
| |
| // Get the pointer before we transfer ownership. |
| MockSupplicantBSSProxy *proxy = supplicant_bss_proxy_.get(); |
| EXPECT_CALL(*proxy, Die()); |
| StartWiFi(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| RemoveBSS("bss0"); |
| // Check this now, to make sure RemoveBSS killed the proxy (rather |
| // than TearDown). |
| Mock::VerifyAndClearExpectations(proxy); |
| } |
| |
| TEST_F(WiFiMainTest, FlushBSSOnResume) { |
| const struct timeval resume_time = {1, 0}; |
| const struct timeval scan_done_time = {6, 0}; |
| MockSupplicantInterfaceProxy &supplicant_interface_proxy = |
| *supplicant_interface_proxy_; |
| |
| StartWiFi(); |
| |
| EXPECT_CALL(time_, GetTimeMonotonic(_)) |
| .WillOnce(DoAll(SetArgumentPointee<0>(resume_time), Return(0))) |
| .WillOnce(DoAll(SetArgumentPointee<0>(scan_done_time), Return(0))); |
| EXPECT_CALL(supplicant_interface_proxy, |
| FlushBSS(WiFi::kMaxBSSResumeAgeSeconds + 5)); |
| OnAfterResume(); |
| ReportScanDone(); |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerIdle) { |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| ReportScanDone(); |
| CancelScanTimer(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| FireScanTimer(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); // Automatically re-armed. |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerScanning) { |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| CancelScanTimer(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| |
| // Should not call Scan, since we're already scanning. |
| // (Scanning is triggered by StartWiFi.) |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| FireScanTimer(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); // Automatically re-armed. |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerConnecting) { |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, 0, kNetworkModeAdHoc); |
| ReportScanDone(); |
| WiFiService *service(GetServices().begin()->get()); |
| InitiateConnect(service); |
| CancelScanTimer(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| FireScanTimer(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); // Automatically re-armed. |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerReconfigured) { |
| StartWiFi(); |
| CancelScanTimer(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| |
| SetScanInterval(1); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerResetOnScanDone) { |
| StartWiFi(); |
| CancelScanTimer(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| |
| ReportScanDone(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerStopOnZeroInterval) { |
| StartWiFi(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); |
| |
| SetScanInterval(0); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, ScanOnDisconnectWithHidden) { |
| Error e; |
| scoped_refptr<MockProfile> profile( |
| new NiceMock<MockProfile>(control_interface(), manager(), "")); |
| WiFiServiceRefPtr hidden_service = |
| GetServiceInner(flimflam::kTypeWifi, "hidden_ssid", |
| flimflam::kModeManaged, NULL, NULL, true, &e); |
| hidden_service->set_profile(profile); |
| |
| StartWiFi(); |
| WiFiEndpointRefPtr ap = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiServiceRefPtr service = CreateServiceForEndpoint(*ap); |
| ReportBSS("an_ap", ap->ssid_string(), ap->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| InitiateConnect(service); |
| ReportCurrentBSSChanged("an_ap"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| dispatcher_.DispatchPendingEvents(); |
| |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), |
| Scan(HasHiddenSSID("hidden_ssid"))); |
| ReportCurrentBSSChanged(wpa_supplicant::kCurrentBSSNull); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, NoScanOnDisconnectWithoutHidden) { |
| StartWiFi(); |
| WiFiEndpointRefPtr ap = MakeEndpoint("an_ssid", "00:01:02:03:04:05"); |
| WiFiServiceRefPtr service = CreateServiceForEndpoint(*ap); |
| ReportBSS("an_ap", ap->ssid_string(), ap->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| InitiateConnect(service); |
| ReportCurrentBSSChanged("an_ap"); |
| ReportStateChanged(wpa_supplicant::kInterfaceStateCompleted); |
| dispatcher_.DispatchPendingEvents(); |
| |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| ReportCurrentBSSChanged(wpa_supplicant::kCurrentBSSNull); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, LinkMonitorFailure) { |
| StartWiFi(); |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| MockLinkMonitor *link_monitor = new StrictMock<MockLinkMonitor>(); |
| SetLinkMonitor(link_monitor); |
| EXPECT_CALL(*link_monitor, IsGatewayFound()) |
| .WillOnce(Return(false)) |
| .WillRepeatedly(Return(true)); |
| EXPECT_CALL(log, Log(logging::LOG_INFO, _, |
| EndsWith("gateway was never found."))).Times(1); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Reassociate()).Times(0); |
| OnLinkMonitorFailure(); |
| EXPECT_CALL(log, Log(logging::LOG_INFO, _, |
| EndsWith("Called Reassociate()."))).Times(1); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Reassociate()).Times(1); |
| OnLinkMonitorFailure(); |
| OnSupplicantVanish(); |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, |
| EndsWith("Cannot reassociate."))).Times(1); |
| OnLinkMonitorFailure(); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsOpen) { |
| Error e; |
| WiFiServiceRefPtr service = GetOpenService( |
| flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, &e); |
| ReportStateChanged(wpa_supplicant::kInterfaceState4WayHandshake); |
| EXPECT_FALSE(service->has_ever_connected()); |
| EXPECT_FALSE(wifi()->SuspectCredentials(*service)); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsWPANeverConnected) { |
| Error e; |
| WiFiServiceRefPtr service = |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWpa, "abcdefgh", &e); |
| ReportStateChanged(wpa_supplicant::kInterfaceState4WayHandshake); |
| EXPECT_FALSE(service->has_ever_connected()); |
| EXPECT_TRUE(wifi()->SuspectCredentials(*service)); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsWPAPreviouslyConnected) { |
| Error e; |
| WiFiServiceRefPtr service = |
| GetService(flimflam::kTypeWifi, "an_ssid", flimflam::kModeManaged, |
| flimflam::kSecurityWpa, "abcdefgh", &e); |
| ReportStateChanged(wpa_supplicant::kInterfaceState4WayHandshake); |
| service->has_ever_connected_ = true; |
| EXPECT_FALSE(wifi()->SuspectCredentials(*service)); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsYieldFailure) { |
| ScopedMockLog log; |
| Error e; |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityWpa); |
| SetPendingService(service); |
| ReportStateChanged(wpa_supplicant::kInterfaceState4WayHandshake); |
| EXPECT_FALSE(service->has_ever_connected()); |
| |
| EXPECT_CALL(*service, SetFailure(Service::kFailureBadPassphrase)); |
| EXPECT_CALL(*service, SetFailureSilent(_)).Times(0); |
| EXPECT_CALL(*service, SetState(_)).Times(0); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith("Bad passphrase?"))); |
| ReportCurrentBSSChanged(wpa_supplicant::kCurrentBSSNull); |
| } |
| |
| // Scanning tests will use a mock of the event dispatcher instead of a real |
| // one. |
| class WiFiTimerTest : public WiFiObjectTest { |
| public: |
| WiFiTimerTest() : WiFiObjectTest(&mock_dispatcher_) {} |
| |
| protected: |
| void ExpectInitialScanSequence(); |
| |
| StrictMock<MockEventDispatcher> mock_dispatcher_; |
| }; |
| |
| void WiFiTimerTest::ExpectInitialScanSequence() { |
| // Choose a number of iterations some multiple higher than the fast scan |
| // count. |
| const int kScanTimes = WiFi::kNumFastScanAttempts * 4; |
| |
| // Each time we call FireScanTimer() below, WiFi will post a task to actually |
| // run Scan() on the wpa_supplicant proxy. |
| EXPECT_CALL(mock_dispatcher_, PostTask(_)) |
| .Times(kScanTimes); |
| { |
| InSequence seq; |
| // The scans immediately after the initial scan should happen at the short |
| // interval. If we add the initial scan (not invoked in this function) to |
| // the ones in the expectation below, we get WiFi::kNumFastScanAttempts at |
| // the fast scan interval. |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask( |
| _, WiFi::kFastScanIntervalSeconds * 1000)) |
| .Times(WiFi::kNumFastScanAttempts - 1) |
| .WillRepeatedly(Return(true)); |
| |
| // After this, the WiFi device should use the normal scan interval. |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask( |
| _, GetScanInterval() * 1000)) |
| .Times(kScanTimes - WiFi::kNumFastScanAttempts + 1) |
| .WillRepeatedly(Return(true)); |
| |
| for (int i = 0; i < kScanTimes; i++) { |
| FireScanTimer(); |
| } |
| } |
| } |
| |
| TEST_F(WiFiTimerTest, FastRescan) { |
| // This PostTask is a result of the call to Scan(NULL), and is meant to |
| // post a task to call Scan() on the wpa_supplicant proxy immediately. |
| EXPECT_CALL(mock_dispatcher_, PostTask(_)); |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask( |
| _, WiFi::kFastScanIntervalSeconds * 1000)) |
| .WillOnce(Return(true)); |
| StartWiFi(); |
| |
| ExpectInitialScanSequence(); |
| |
| // If we end up disconnecting, the sequence should repeat. |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask( |
| _, WiFi::kFastScanIntervalSeconds * 1000)) |
| .WillOnce(Return(true)); |
| RestartFastScanAttempts(); |
| |
| ExpectInitialScanSequence(); |
| } |
| |
| TEST_F(WiFiTimerTest, ReconnectTimer) { |
| EXPECT_CALL(mock_dispatcher_, PostTask(_)).Times(AnyNumber()); |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _)).Times(AnyNumber()); |
| SetupConnectedService(DBus::Path()); |
| Mock::VerifyAndClearExpectations(&mock_dispatcher_); |
| |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask( |
| _, GetReconnectTimeoutSeconds() * 1000)).Times(1); |
| StartReconnectTimer(); |
| Mock::VerifyAndClearExpectations(&mock_dispatcher_); |
| StopReconnectTimer(); |
| |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask( |
| _, GetReconnectTimeoutSeconds() * 1000)).Times(1); |
| StartReconnectTimer(); |
| Mock::VerifyAndClearExpectations(&mock_dispatcher_); |
| GetReconnectTimeoutCallback().callback().Run(); |
| |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask( |
| _, GetReconnectTimeoutSeconds() * 1000)).Times(1); |
| StartReconnectTimer(); |
| Mock::VerifyAndClearExpectations(&mock_dispatcher_); |
| |
| EXPECT_CALL(mock_dispatcher_, PostDelayedTask( |
| _, GetReconnectTimeoutSeconds() * 1000)).Times(0); |
| StartReconnectTimer(); |
| } |
| |
| TEST_F(WiFiMainTest, EAPCertification) { |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurity8021x); |
| EXPECT_CALL(*service, AddEAPCertification(_, _)).Times(0); |
| |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith("no current service."))); |
| map<string, ::DBus::Variant> args; |
| ReportCertification(args); |
| Mock::VerifyAndClearExpectations(&log); |
| |
| SetCurrentService(service); |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith("no depth parameter."))); |
| ReportCertification(args); |
| Mock::VerifyAndClearExpectations(&log); |
| |
| const uint32 kDepth = 123; |
| args[wpa_supplicant::kInterfacePropertyDepth].writer().append_uint32(kDepth); |
| |
| EXPECT_CALL(log, |
| Log(logging::LOG_ERROR, _, EndsWith("no subject parameter."))); |
| ReportCertification(args); |
| Mock::VerifyAndClearExpectations(&log); |
| |
| const string kSubject("subject"); |
| args[wpa_supplicant::kInterfacePropertySubject].writer() |
| .append_string(kSubject.c_str()); |
| EXPECT_CALL(*service, AddEAPCertification(kSubject, kDepth)).Times(1); |
| ReportCertification(args); |
| } |
| |
| TEST_F(WiFiMainTest, PendingScanDoesNotCrashAfterStop) { |
| // Scan is one task that should be skipped after Stop. Others are |
| // skipped by the same mechanism (invalidating weak pointers), so we |
| // don't test them individually. |
| // |
| // Note that we can't test behavior by setting expectations on the |
| // supplicant_interface_proxy_, since that is destroyed when we StopWiFi(). |
| StartWiFi(); |
| StopWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| } // namespace shill |