| // 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 <linux/if.h> |
| #include <linux/netlink.h> // Needs typedefs from sys/socket.h. |
| #include <netinet/ether.h> |
| #include <sys/socket.h> |
| |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include <base/file_util.h> |
| #include <base/memory/ref_counted.h> |
| #include <base/memory/scoped_ptr.h> |
| #include <base/string_number_conversions.h> |
| #include <base/string_split.h> |
| #include <base/string_util.h> |
| #include <base/stringprintf.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/geolocation_info.h" |
| #include "shill/ieee80211.h" |
| #include "shill/key_value_store.h" |
| #include "shill/logging.h" |
| #include "shill/manager.h" |
| #include "shill/mock_adaptors.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_netlink_manager.h" |
| #include "shill/mock_profile.h" |
| #include "shill/mock_rtnl_handler.h" |
| #include "shill/mock_scan_session.h" |
| #include "shill/mock_store.h" |
| #include "shill/mock_supplicant_bss_proxy.h" |
| #include "shill/mock_supplicant_eap_state_handler.h" |
| #include "shill/mock_supplicant_interface_proxy.h" |
| #include "shill/mock_supplicant_network_proxy.h" |
| #include "shill/mock_supplicant_process_proxy.h" |
| #include "shill/mock_time.h" |
| #include "shill/mock_wifi_provider.h" |
| #include "shill/mock_wifi_service.h" |
| #include "shill/netlink_message_matchers.h" |
| #include "shill/nice_mock_control.h" |
| #include "shill/nl80211_message.h" |
| #include "shill/property_store_unittest.h" |
| #include "shill/proxy_factory.h" |
| #include "shill/scan_session.h" |
| #include "shill/technology.h" |
| #include "shill/wifi_endpoint.h" |
| #include "shill/wifi_service.h" |
| #include "shill/wpa_supplicant.h" |
| |
| |
| using base::FilePath; |
| using std::map; |
| using std::string; |
| using std::vector; |
| using ::testing::_; |
| using ::testing::AnyNumber; |
| using ::testing::AtLeast; |
| using ::testing::DefaultValue; |
| using ::testing::DoAll; |
| using ::testing::EndsWith; |
| using ::testing::HasSubstr; |
| using ::testing::InSequence; |
| using ::testing::Invoke; |
| using ::testing::InvokeWithoutArgs; |
| using ::testing::MakeMatcher; |
| using ::testing::Matcher; |
| using ::testing::MatcherInterface; |
| using ::testing::MatchResultListener; |
| using ::testing::Mock; |
| using ::testing::NiceMock; |
| using ::testing::NotNull; |
| using ::testing::Return; |
| using ::testing::ReturnRef; |
| using ::testing::SaveArg; |
| using ::testing::SetArgumentPointee; |
| using ::testing::StrEq; |
| using ::testing::StrictMock; |
| using ::testing::Test; |
| using ::testing::Throw; |
| using ::testing::Values; |
| |
| namespace shill { |
| |
| namespace { |
| |
| const uint16_t kNl80211FamilyId = 0x13; |
| const uint16_t kRandomScanFrequency1 = 5600; |
| const uint16_t kRandomScanFrequency2 = 5560; |
| const uint16_t kRandomScanFrequency3 = 2422; |
| |
| } // namespace |
| |
| class WiFiPropertyTest : public PropertyStoreTest { |
| public: |
| WiFiPropertyTest() |
| : device_(new WiFi(control_interface(), |
| NULL, NULL, manager(), "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)); |
| ASSERT_TRUE(error.is_set()); // name() may be invalid otherwise |
| EXPECT_EQ(invalid_args(), error.name()); |
| } |
| |
| { |
| ::DBus::Error error; |
| EXPECT_TRUE(DBusAdaptor::SetProperty( |
| device_->mutable_store(), |
| flimflam::kBgscanMethodProperty, |
| DBusAdaptor::StringToVariant( |
| WPASupplicant::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(WPASupplicant::kNetworkBgscanMethodLearn, |
| WiFi::kDefaultBgscanMethod); |
| EXPECT_TRUE(device_->bgscan_method_.empty()); |
| |
| string method; |
| Error unused_error; |
| EXPECT_TRUE(device_->store().GetStringProperty( |
| flimflam::kBgscanMethodProperty, &method, &unused_error)); |
| EXPECT_EQ(WiFi::kDefaultBgscanMethod, method); |
| EXPECT_EQ(WPASupplicant::kNetworkBgscanMethodSimple, method); |
| |
| ::DBus::Error error; |
| EXPECT_TRUE(DBusAdaptor::SetProperty( |
| device_->mutable_store(), |
| flimflam::kBgscanMethodProperty, |
| DBusAdaptor::StringToVariant( |
| WPASupplicant::kNetworkBgscanMethodLearn), |
| &error)); |
| EXPECT_EQ(WPASupplicant::kNetworkBgscanMethodLearn, device_->bgscan_method_); |
| EXPECT_TRUE(device_->store().GetStringProperty( |
| flimflam::kBgscanMethodProperty, &method, &unused_error)); |
| EXPECT_EQ(WPASupplicant::kNetworkBgscanMethodLearn, method); |
| |
| EXPECT_TRUE(DBusAdaptor::ClearProperty( |
| device_->mutable_store(), flimflam::kBgscanMethodProperty, &error)); |
| EXPECT_TRUE(device_->store().GetStringProperty( |
| flimflam::kBgscanMethodProperty, &method, &unused_error)); |
| EXPECT_EQ(WiFi::kDefaultBgscanMethod, method); |
| EXPECT_TRUE(device_->bgscan_method_.empty()); |
| } |
| |
| MATCHER_P(EndpointMatch, endpoint, "") { |
| return |
| arg->ssid() == endpoint->ssid() && |
| arg->network_mode() == endpoint->network_mode() && |
| arg->security_mode() == endpoint->security_mode(); |
| } |
| |
| |
| class WiFiObjectTest : public ::testing::TestWithParam<string> { |
| public: |
| explicit WiFiObjectTest(EventDispatcher *dispatcher) |
| : event_dispatcher_(dispatcher), |
| metrics_(NULL), |
| manager_(&control_interface_, NULL, &metrics_, &glib_), |
| device_info_(&control_interface_, dispatcher, &metrics_, &manager_), |
| wifi_(new WiFi(&control_interface_, |
| dispatcher, |
| &metrics_, |
| &manager_, |
| kDeviceName, |
| kDeviceAddress, |
| 0)), |
| bss_counter_(0), |
| supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()), |
| supplicant_bss_proxy_( |
| new NiceMock<MockSupplicantBSSProxy>()), |
| dhcp_config_(new MockDHCPConfig(&control_interface_, |
| kDeviceName)), |
| dbus_manager_(new NiceMock<MockDBusManager>()), |
| adaptor_(new DeviceMockAdaptor()), |
| eap_state_handler_(new NiceMock<MockSupplicantEAPStateHandler>()), |
| supplicant_interface_proxy_( |
| new NiceMock<MockSupplicantInterfaceProxy>()), |
| proxy_factory_(this) { |
| InstallMockScanSession(); |
| ::testing::DefaultValue< ::DBus::Path>::Set("/default/path"); |
| |
| ON_CALL(dhcp_provider_, CreateConfig(_, _, _, _)). |
| WillByDefault(Return(dhcp_config_)); |
| ON_CALL(*dhcp_config_.get(), RequestIP()). |
| WillByDefault(Return(true)); |
| ON_CALL(proxy_factory_, CreateSupplicantNetworkProxy(_, _)). |
| WillByDefault(InvokeWithoutArgs( |
| this, &WiFiObjectTest::CreateSupplicantNetworkProxy)); |
| Nl80211Message::SetMessageType(kNl80211FamilyId); |
| |
| // Transfers ownership. |
| manager_.dbus_manager_.reset(dbus_manager_); |
| wifi_->eap_state_handler_.reset(eap_state_handler_); |
| |
| wifi_->provider_ = &wifi_provider_; |
| wifi_->time_ = &time_; |
| wifi_->netlink_manager_ = &netlink_manager_; |
| wifi_->progressive_scan_enabled_ = true; |
| wifi_->adaptor_.reset(adaptor_); // Transfers ownership. |
| |
| // The following is only useful when a real |ScanSession| is used; it is |
| // ignored by |MockScanSession|. |
| wifi_->all_scan_frequencies_.insert(kRandomScanFrequency1); |
| wifi_->all_scan_frequencies_.insert(kRandomScanFrequency2); |
| wifi_->all_scan_frequencies_.insert(kRandomScanFrequency3); |
| } |
| |
| 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(*supplicant_bss_proxy_, Die()).Times(AnyNumber()); |
| } |
| |
| virtual void TearDown() { |
| EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(_)) |
| .WillRepeatedly(Return(reinterpret_cast<WiFiService *>(NULL))); |
| 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()); |
| } |
| |
| // Needs to be public since it is called via Invoke(). |
| void ThrowDBusError() { |
| throw DBus::Error("SomeDBusType", "A handy message"); |
| } |
| void ResetPendingService() { |
| SetPendingService(NULL); |
| } |
| |
| size_t GetScanFrequencyCount() const { |
| return wifi_->all_scan_frequencies_.size(); |
| } |
| |
| void SetScanSize(int min, int max) { |
| wifi_->min_frequencies_to_scan_ = min; |
| wifi_->max_frequencies_to_scan_ = max; |
| } |
| |
| // This clears WiFi::scan_session_, thereby allowing WiFi::Scan to create a |
| // real scan session. |
| void ClearScanSession() { |
| wifi_->scan_session_.reset(); |
| } |
| |
| bool IsScanSessionNull() { |
| return !wifi_->scan_session_; |
| } |
| |
| void InstallMockScanSession() { |
| WiFiProvider::FrequencyCountList previous_frequencies; |
| std::set<uint16_t> available_frequencies; |
| ScanSession::FractionList fractions; |
| ScanSession::OnScanFailed null_callback; |
| scan_session_ = new MockScanSession(&netlink_manager_, |
| event_dispatcher_, |
| previous_frequencies, |
| available_frequencies, |
| 0, |
| fractions, |
| 0, |
| 0, |
| null_callback, |
| NULL); |
| wifi_->scan_session_.reset(scan_session_); |
| } |
| |
| // Or DisableProgressiveScan()... |
| void EnableFullScan() { |
| wifi_->progressive_scan_enabled_ = false; |
| } |
| |
| void OnTriggerScanResponse(const Nl80211Message &message) { |
| wifi_->scan_session_->OnTriggerScanResponse(message); |
| } |
| |
| void SetScanState(WiFi::ScanState new_state, WiFi::ScanMethod new_method) { |
| wifi_->SetScanState(new_state, new_method); |
| } |
| |
| void VerifyScanState(WiFi::ScanState state, WiFi::ScanMethod method) { |
| EXPECT_EQ(state, wifi_->scan_state_); |
| EXPECT_EQ(method, wifi_->scan_method_); |
| } |
| |
| 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( |
| SupplicantEventDelegateInterface */*delegate*/, |
| 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)); |
| |
| MOCK_METHOD2(CreateSupplicantNetworkProxy, |
| SupplicantNetworkProxyInterface *( |
| 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_; |
| }; |
| |
| // Simulate the course of events when the last enpoint of a service is |
| // removed. |
| class EndpointRemovalHandler { |
| public: |
| EndpointRemovalHandler(WiFiRefPtr wifi, const WiFiServiceRefPtr &service) |
| : wifi_(wifi), service_(service) {} |
| virtual ~EndpointRemovalHandler() {} |
| |
| WiFiServiceRefPtr OnEndpointRemoved( |
| const WiFiEndpointConstRefPtr &endpoint) { |
| wifi_->DisassociateFromService(service_); |
| return service_; |
| } |
| |
| private: |
| WiFiRefPtr wifi_; |
| WiFiServiceRefPtr service_; |
| }; |
| |
| EndpointRemovalHandler *MakeEndpointRemovalHandler( |
| const WiFiServiceRefPtr &service) { |
| return new EndpointRemovalHandler(wifi_, service); |
| } |
| void CancelScanTimer() { |
| wifi_->scan_timer_callback_.Cancel(); |
| } |
| // This function creates a new endpoint with a mode set to |mode|. We |
| // synthesize new |path| and |bssid| values, since we don't really care |
| // what they are for unit tests. If "use_ssid" is true, we used the |
| // passed-in ssid, otherwise we create a synthesized value for it as well. |
| WiFiEndpointRefPtr MakeNewEndpoint(const char *mode, |
| bool use_ssid, |
| string *ssid, |
| string *path, |
| string *bssid) { |
| bss_counter_++; |
| if (!use_ssid) { |
| *ssid = base::StringPrintf("ssid%d", bss_counter_); |
| } |
| *path = base::StringPrintf("/interface/bss%d", bss_counter_); |
| *bssid = base::StringPrintf("00:00:00:00:00:%02x", bss_counter_); |
| WiFiEndpointRefPtr endpoint = MakeEndpointWithMode(*ssid, *bssid, mode); |
| EXPECT_CALL(wifi_provider_, |
| OnEndpointAdded(EndpointMatch(endpoint))).Times(1); |
| return endpoint; |
| } |
| WiFiEndpointRefPtr MakeEndpoint(const string &ssid, const string &bssid) { |
| return MakeEndpointWithMode(ssid, bssid, kNetworkModeInfrastructure); |
| } |
| WiFiEndpointRefPtr MakeEndpointWithMode( |
| const string &ssid, const string &bssid, const string &mode) { |
| return WiFiEndpoint::MakeOpenEndpoint( |
| &proxy_factory_, NULL, ssid, bssid, mode, 0, 0); |
| } |
| MockWiFiServiceRefPtr MakeMockServiceWithSSID( |
| vector<uint8_t> ssid, const std::string &security) { |
| return new NiceMock<MockWiFiService>( |
| &control_interface_, |
| event_dispatcher_, |
| &metrics_, |
| &manager_, |
| &wifi_provider_, |
| ssid, |
| flimflam::kModeManaged, |
| security, |
| false); |
| } |
| MockWiFiServiceRefPtr MakeMockService(const std::string &security) { |
| return MakeMockServiceWithSSID(vector<uint8_t>(1, 'a'), security); |
| } |
| ::DBus::Path MakeNewEndpointAndService(int16_t signal_strength, |
| uint16 frequency, |
| const char *mode, |
| WiFiEndpointRefPtr *endpoint_ptr, |
| MockWiFiServiceRefPtr *service_ptr) { |
| string ssid; |
| ::DBus::Path path; |
| string bssid; |
| WiFiEndpointRefPtr endpoint = |
| MakeNewEndpoint(mode, false, &ssid, &path, &bssid); |
| MockWiFiServiceRefPtr service = |
| MakeMockServiceWithSSID(endpoint->ssid(), endpoint->security_mode()); |
| EXPECT_CALL(wifi_provider_, FindServiceForEndpoint(EndpointMatch(endpoint))) |
| .WillRepeatedly(Return(service)); |
| ON_CALL(*service, GetEndpointCount()).WillByDefault(Return(1)); |
| ReportBSS(path, ssid, bssid, signal_strength, frequency, mode); |
| if (service_ptr) { |
| *service_ptr = service; |
| } |
| if (endpoint_ptr) { |
| *endpoint_ptr = endpoint; |
| } |
| return path; |
| } |
| ::DBus::Path AddEndpointToService( |
| WiFiServiceRefPtr service, |
| int16_t signal_strength, |
| uint16 frequency, |
| const char *mode, |
| WiFiEndpointRefPtr *endpoint_ptr) { |
| string ssid(service->ssid().begin(), service->ssid().end()); |
| ::DBus::Path path; |
| string bssid; |
| WiFiEndpointRefPtr endpoint = |
| MakeNewEndpoint(mode, true, &ssid, &path, &bssid); |
| EXPECT_CALL(wifi_provider_, FindServiceForEndpoint(EndpointMatch(endpoint))) |
| .WillRepeatedly(Return(service)); |
| ReportBSS(path, ssid, bssid, signal_strength, frequency, mode); |
| if (endpoint_ptr) { |
| *endpoint_ptr = endpoint; |
| } |
| return path; |
| } |
| void InitiateConnect(WiFiServiceRefPtr service) { |
| map<string, ::DBus::Variant> params; |
| wifi_->ConnectTo(service, params); |
| } |
| void InitiateDisconnect(WiFiServiceRefPtr service) { |
| wifi_->DisconnectFrom(service); |
| } |
| MockWiFiServiceRefPtr SetupConnectingService( |
| const DBus::Path &network_path, |
| WiFiEndpointRefPtr *endpoint_ptr, |
| ::DBus::Path *bss_path_ptr) { |
| if (!network_path.empty()) { |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), AddNetwork(_)) |
| .WillOnce(Return(network_path)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), SelectNetwork(network_path)); |
| } |
| |
| MockWiFiServiceRefPtr service; |
| WiFiEndpointRefPtr endpoint; |
| ::DBus::Path bss_path(MakeNewEndpointAndService( |
| 0, 0, kNetworkModeAdHoc, &endpoint, &service)); |
| EXPECT_CALL(*service, SetState(Service::kStateAssociating)); |
| InitiateConnect(service); |
| Mock::VerifyAndClearExpectations(service); |
| EXPECT_FALSE(GetPendingTimeout().IsCancelled()); |
| if (endpoint_ptr) { |
| *endpoint_ptr = endpoint; |
| } |
| if (bss_path_ptr) { |
| *bss_path_ptr = bss_path; |
| } |
| return service; |
| } |
| |
| MockWiFiServiceRefPtr SetupConnectedService( |
| const DBus::Path &network_path, |
| WiFiEndpointRefPtr *endpoint_ptr, |
| ::DBus::Path *bss_path_ptr) { |
| WiFiEndpointRefPtr endpoint; |
| ::DBus::Path bss_path; |
| MockWiFiServiceRefPtr service = |
| SetupConnectingService(network_path, &endpoint, &bss_path); |
| if (endpoint_ptr) { |
| *endpoint_ptr = endpoint; |
| } |
| if (bss_path_ptr) { |
| *bss_path_ptr = bss_path; |
| } |
| EXPECT_CALL(*service, NotifyCurrentEndpoint(EndpointMatch(endpoint))); |
| ReportCurrentBSSChanged(bss_path); |
| EXPECT_TRUE(GetPendingTimeout().IsCancelled()); |
| Mock::VerifyAndClearExpectations(service); |
| |
| EXPECT_CALL(*service, SetState(Service::kStateConfiguring)); |
| EXPECT_CALL(*dhcp_provider(), CreateConfig(_, _, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber()); |
| ReportStateChanged(WPASupplicant::kInterfaceStateCompleted); |
| Mock::VerifyAndClearExpectations(service); |
| |
| EXPECT_EQ(service, GetCurrentService()); |
| return service; |
| } |
| void FireScanTimer() { |
| wifi_->ScanTimerHandler(); |
| } |
| void TriggerFullScan() { |
| wifi_->Scan(Device::kFullScan, NULL); |
| } |
| 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_; |
| } |
| // 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 *GetSupplicantInterfaceProxyFromWiFi() { |
| return dynamic_cast<MockSupplicantInterfaceProxy *>( |
| wifi_->supplicant_interface_proxy_.get()); |
| } |
| // This function returns the supplicant interface proxy whether |
| // or not we have passed the instantiated object to the WiFi instance |
| // from WiFiObjectTest, so tests don't need to worry about when they |
| // set expectations relative to StartWiFi(). |
| MockSupplicantInterfaceProxy *GetSupplicantInterfaceProxy() { |
| MockSupplicantInterfaceProxy *proxy = GetSupplicantInterfaceProxyFromWiFi(); |
| return proxy ? proxy : supplicant_interface_proxy_.get(); |
| } |
| MockSupplicantNetworkProxy *CreateSupplicantNetworkProxy() { |
| return new NiceMock<MockSupplicantNetworkProxy>(); |
| } |
| const string &GetSupplicantState() { |
| return wifi_->supplicant_state_; |
| } |
| void ClearCachedCredentials(const WiFiService *service) { |
| return wifi_->ClearCachedCredentials(service); |
| } |
| void NotifyEndpointChanged(const WiFiEndpointConstRefPtr &endpoint) { |
| wifi_->NotifyEndpointChanged(endpoint); |
| } |
| bool RemoveNetwork(const ::DBus::Path &network) { |
| return wifi_->RemoveNetwork(network); |
| } |
| 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 ReportIPConfigComplete() { |
| wifi_->OnIPConfigUpdated(dhcp_config_, true); |
| } |
| void ReportLinkUp() { |
| wifi_->LinkEvent(IFF_LOWER_UP, IFF_LOWER_UP); |
| } |
| void ReportScanDone() { |
| // Eliminate |scan_session| so |ScanDoneTask| doesn't launch another scan. |
| wifi_->scan_session_.reset(); |
| wifi_->ScanDoneTask(); |
| // Make a new |scan_session| so that future scanning is done with the mock. |
| InstallMockScanSession(); |
| } |
| void ReportScanDoneKeepScanSession() { |
| wifi_->ScanDoneTask(); |
| } |
| void ReportCurrentBSSChanged(const string &new_bss) { |
| wifi_->CurrentBSSChanged(new_bss); |
| } |
| void ReportStateChanged(const string &new_state) { |
| wifi_->StateChanged(new_state); |
| } |
| void ReportWiFiDebugScopeChanged(bool enabled) { |
| wifi_->OnWiFiDebugScopeChanged(enabled); |
| } |
| void SetPendingService(const WiFiServiceRefPtr &service) { |
| wifi_->pending_service_ = service; |
| } |
| bool SetScanInterval(uint16_t interval_seconds, Error *error) { |
| return wifi_->SetScanInterval(interval_seconds, error); |
| } |
| 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_; |
| } |
| 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 ReportEAPEvent(const string &status, const string ¶meter) { |
| wifi_->EAPEventTask(status, parameter); |
| } |
| |
| void RestartFastScanAttempts() { |
| wifi_->RestartFastScanAttempts(); |
| } |
| |
| void StartReconnectTimer() { |
| wifi_->StartReconnectTimer(); |
| } |
| |
| void StopReconnectTimer() { |
| wifi_->StopReconnectTimer(); |
| } |
| |
| void SetLinkMonitor(LinkMonitor *link_monitor) { |
| wifi_->set_link_monitor(link_monitor); |
| } |
| |
| bool SuspectCredentials(const WiFiService &service, |
| Service::ConnectFailure *failure) { |
| return wifi_->SuspectCredentials(service, failure); |
| } |
| |
| void OnLinkMonitorFailure() { |
| wifi_->OnLinkMonitorFailure(); |
| } |
| |
| bool SetBgscanShortInterval(const uint16 &interval, Error *error) { |
| return wifi_->SetBgscanShortInterval(interval, error); |
| } |
| |
| bool SetBgscanSignalThreshold(const int32 &threshold, Error *error) { |
| return wifi_->SetBgscanSignalThreshold(threshold, error); |
| } |
| |
| NiceMockControl *control_interface() { |
| return &control_interface_; |
| } |
| |
| MockMetrics *metrics() { |
| return &metrics_; |
| } |
| |
| 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_; |
| } |
| |
| MockWiFiProvider *wifi_provider() { |
| return &wifi_provider_; |
| } |
| |
| EventDispatcher *event_dispatcher_; |
| MockScanSession *scan_session_; // Owned by |wifi_|. |
| NiceMock<MockRTNLHandler> rtnl_handler_; |
| MockTime time_; |
| |
| private: |
| NiceMockControl control_interface_; |
| MockMetrics metrics_; |
| MockGLib glib_; |
| MockManager manager_; |
| MockDeviceInfo device_info_; |
| WiFiRefPtr wifi_; |
| NiceMock<MockWiFiProvider> wifi_provider_; |
| int bss_counter_; |
| |
| // 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<MockSupplicantBSSProxy> supplicant_bss_proxy_; |
| MockDHCPProvider dhcp_provider_; |
| scoped_refptr<MockDHCPConfig> dhcp_config_; |
| |
| // These pointers track mock objects owned by the WiFi device instance |
| // and manager so we can perform expectations against them. |
| MockDBusManager *dbus_manager_; |
| DeviceMockAdaptor *adaptor_; |
| MockSupplicantEAPStateHandler *eap_state_handler_; |
| MockNetlinkManager netlink_manager_; |
| |
| private: |
| scoped_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_; |
| NiceMock<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[WPASupplicant::kBSSPropertySignal].writer(). |
| append_int16(signal_strength); |
| bss_properties[WPASupplicant::kBSSPropertyFrequency].writer(). |
| append_uint16(frequency); |
| bss_properties[WPASupplicant::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(GetSupplicantInterfaceProxyFromWiFi() == NULL); |
| |
| StartWiFi(); |
| EXPECT_FALSE(GetSupplicantProcessProxy() == NULL); |
| EXPECT_FALSE(GetSupplicantInterfaceProxyFromWiFi() == NULL); |
| } |
| |
| TEST_F(WiFiMainTest, SupplicantPresent) { |
| EXPECT_FALSE(GetSupplicantPresent()); |
| } |
| |
| TEST_F(WiFiMainTest, OnSupplicantAppearStarted) { |
| EXPECT_TRUE(GetSupplicantProcessProxy() == NULL); |
| |
| EXPECT_CALL(*dbus_manager_, WatchName(WPASupplicant::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) { |
| StartWiFi(); |
| WiFiEndpointRefPtr endpoint; |
| WiFiServiceRefPtr service( |
| SetupConnectedService(DBus::Path(), &endpoint, NULL)); |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, |
| EndsWith("silently resetting current_service_."))); |
| EXPECT_CALL(*manager(), DeregisterDevice(_)) |
| .WillOnce(InvokeWithoutArgs(this, &WiFiObjectTest::StopWiFi)); |
| scoped_ptr<EndpointRemovalHandler> handler( |
| MakeEndpointRemovalHandler(service)); |
| EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint))) |
| .WillOnce(Invoke(handler.get(), |
| &EndpointRemovalHandler::OnEndpointRemoved)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()).Times(0); |
| EXPECT_CALL(*manager(), RegisterDevice(_)); |
| OnSupplicantVanish(); |
| EXPECT_TRUE(GetCurrentService() == NULL); |
| } |
| |
| TEST_F(WiFiMainTest, CleanStart_FullScan) { |
| EnableFullScan(); |
| 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_TRUE(GetScanTimer().IsCancelled()); |
| StartWiFi(); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); |
| } |
| |
| 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_TRUE(GetScanTimer().IsCancelled()); |
| StartWiFi(); |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, ClearCachedCredentials) { |
| StartWiFi(); |
| DBus::Path network = "/test/path"; |
| WiFiServiceRefPtr service(SetupConnectedService(network, NULL, NULL)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(network)); |
| ClearCachedCredentials(service); |
| } |
| |
| TEST_F(WiFiMainTest, NotifyEndpointChanged) { |
| WiFiEndpointRefPtr endpoint = |
| MakeEndpointWithMode("ssid", "00:00:00:00:00:00", kNetworkModeAdHoc); |
| EXPECT_CALL(*wifi_provider(), OnEndpointUpdated(EndpointMatch(endpoint))); |
| NotifyEndpointChanged(endpoint); |
| } |
| |
| TEST_F(WiFiMainTest, RemoveNetwork) { |
| DBus::Path network = "/test/path"; |
| StartWiFi(); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(network)); |
| EXPECT_TRUE(RemoveNetwork(network)); |
| } |
| |
| TEST_F(WiFiMainTest, RemoveNetworkWhenSupplicantReturnsNetworkUnknown) { |
| DBus::Path network = "/test/path"; |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(network)) |
| .WillRepeatedly(Throw( |
| DBus::Error( |
| "fi.w1.wpa_supplicant1.NetworkUnknown", |
| "test threw fi.w1.wpa_supplicant1.NetworkUnknown"))); |
| StartWiFi(); |
| EXPECT_TRUE(RemoveNetwork(network)); |
| } |
| |
| TEST_F(WiFiMainTest, UseArpGateway) { |
| EXPECT_CALL(dhcp_provider_, CreateConfig(kDeviceName, _, _, true)) |
| .WillOnce(Return(dhcp_config_)); |
| const_cast<WiFi *>(wifi().get())->AcquireIPConfig(); |
| } |
| |
| TEST_F(WiFiMainTest, RemoveNetworkWhenSupplicantReturnsInvalidArgs) { |
| DBus::Path network = "/test/path"; |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(network)) |
| .WillRepeatedly(Throw( |
| DBus::Error( |
| "fi.w1.wpa_supplicant1.InvalidArgs", |
| "test threw fi.w1.wpa_supplicant1.InvalidArgs"))); |
| StartWiFi(); |
| EXPECT_FALSE(RemoveNetwork(network)); |
| } |
| |
| TEST_F(WiFiMainTest, RemoveNetworkWhenSupplicantReturnsUnknownError) { |
| DBus::Path network = "/test/path"; |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(network)) |
| .WillRepeatedly(Throw( |
| DBus::Error( |
| "fi.w1.wpa_supplicant1.UnknownError", |
| "test threw fi.w1.wpa_supplicant1.UnknownError"))); |
| StartWiFi(); |
| EXPECT_FALSE(RemoveNetwork(network)); |
| } |
| |
| TEST_F(WiFiMainTest, Restart_FullScan) { |
| EnableFullScan(); |
| 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(*GetSupplicantInterfaceProxy(), Scan(_)); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| 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(*scan_session_, InitiateScan()); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, StartClearsState) { |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveAllNetworks()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), FlushBSS(_)); |
| StartWiFi(); |
| } |
| |
| TEST_F(WiFiMainTest, NoScansWhileConnecting_FullScan) { |
| EnableFullScan(); |
| StartWiFi(); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(1); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| SetPendingService(service); |
| // If we're connecting, we ignore scan requests to stay on channel. |
| EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(true)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| TriggerFullScan(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| Mock::VerifyAndClearExpectations(service); |
| EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(false)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(1); |
| TriggerFullScan(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| Mock::VerifyAndClearExpectations(service); |
| // Similarly, ignore scans when our connected service is reconnecting. |
| SetPendingService(NULL); |
| SetCurrentService(service); |
| EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(true)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| TriggerFullScan(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| Mock::VerifyAndClearExpectations(service); |
| // But otherwise we'll honor the request. |
| EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(false)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(1); |
| TriggerFullScan(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| Mock::VerifyAndClearExpectations(service); |
| } |
| |
| TEST_F(WiFiMainTest, NoScansWhileConnecting) { |
| StartWiFi(); |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| SetPendingService(service); |
| // If we're connecting, we ignore scan requests to stay on channel. |
| EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(true)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| TriggerFullScan(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| Mock::VerifyAndClearExpectations(service); |
| EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(false)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(1); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| TriggerFullScan(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| Mock::VerifyAndClearExpectations(service); |
| // Similarly, ignore scans when our connected service is reconnecting. |
| SetPendingService(NULL); |
| SetCurrentService(service); |
| EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(true)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| TriggerFullScan(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| Mock::VerifyAndClearExpectations(service); |
| // But otherwise we'll honor the request. |
| EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(false)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(1); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| TriggerFullScan(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| Mock::VerifyAndClearExpectations(service); |
| } |
| |
| TEST_F(WiFiMainTest, ResumeStartsScanWhenIdle_FullScan) { |
| EnableFullScan(); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| ReportScanDone(); |
| ASSERT_TRUE(wifi()->IsIdle()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| OnAfterResume(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ResumeStartsScanWhenIdle) { |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| ReportScanDone(); |
| ASSERT_TRUE(wifi()->IsIdle()); |
| dispatcher_.DispatchPendingEvents(); |
| OnAfterResume(); |
| EXPECT_TRUE(scan_session_ != NULL); |
| InstallMockScanSession(); |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, SuspendDoesNotStartScan_FullScan) { |
| EnableFullScan(); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| ASSERT_TRUE(wifi()->IsIdle()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| OnBeforeSuspend(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, SuspendDoesNotStartScan) { |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| ASSERT_TRUE(wifi()->IsIdle()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| OnBeforeSuspend(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ResumeDoesNotStartScanWhenNotIdle_FullScan) { |
| EnableFullScan(); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| WiFiServiceRefPtr service(SetupConnectedService(DBus::Path(), NULL, NULL)); |
| EXPECT_FALSE(wifi()->IsIdle()); |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, EndsWith("already connecting or connected."))); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| OnAfterResume(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ResumeDoesNotStartScanWhenNotIdle) { |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| WiFiServiceRefPtr service(SetupConnectedService(DBus::Path(), NULL, NULL)); |
| EXPECT_FALSE(wifi()->IsIdle()); |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, EndsWith("already connecting or connected."))); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| OnAfterResume(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ScanResults) { |
| EXPECT_CALL(*wifi_provider(), OnEndpointAdded(_)).Times(5); |
| 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, ScanCompleted) { |
| StartWiFi(); |
| WiFiEndpointRefPtr ap0 = MakeEndpointWithMode("ssid0", "00:00:00:00:00:00", |
| kNetworkModeAdHoc); |
| WiFiEndpointRefPtr ap1 = MakeEndpoint("ssid1", "00:00:00:00:00:01"); |
| WiFiEndpointRefPtr ap2 = MakeEndpoint("ssid2", "00:00:00:00:00:02"); |
| EXPECT_CALL(*wifi_provider(), OnEndpointAdded(EndpointMatch(ap0))).Times(1); |
| EXPECT_CALL(*wifi_provider(), OnEndpointAdded(EndpointMatch(ap1))).Times(1); |
| EXPECT_CALL(*wifi_provider(), OnEndpointAdded(EndpointMatch(ap2))).Times(1); |
| ReportBSS("bss0", ap0->ssid_string(), ap0->bssid_string(), 0, 0, |
| kNetworkModeAdHoc); |
| ReportBSS("bss1", ap1->ssid_string(), ap1->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| ReportBSS("bss2", ap2->ssid_string(), ap2->bssid_string(), 0, 0, |
| kNetworkModeInfrastructure); |
| ReportScanDone(); |
| Mock::VerifyAndClearExpectations(wifi_provider()); |
| |
| EXPECT_CALL(*wifi_provider(), OnEndpointAdded(_)).Times(0); |
| |
| // BSSes with SSIDs that start with NULL should be filtered. |
| ReportBSS("bss3", string(1, 0), "00:00:00:00:00:03", 3, 0, kNetworkModeAdHoc); |
| |
| // BSSes with empty SSIDs should be filtered. |
| ReportBSS("bss3", string(), "00:00:00:00:00:03", 3, 0, kNetworkModeAdHoc); |
| } |
| |
| TEST_F(WiFiMainTest, LoneBSSRemovedWhileConnected) { |
| StartWiFi(); |
| WiFiEndpointRefPtr endpoint; |
| DBus::Path bss_path; |
| WiFiServiceRefPtr service( |
| SetupConnectedService(DBus::Path(), &endpoint, &bss_path)); |
| scoped_ptr<EndpointRemovalHandler> handler( |
| MakeEndpointRemovalHandler(service)); |
| EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint))) |
| .WillOnce(Invoke(handler.get(), |
| &EndpointRemovalHandler::OnEndpointRemoved)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| RemoveBSS(bss_path); |
| } |
| |
| TEST_F(WiFiMainTest, NonSolitaryBSSRemoved) { |
| StartWiFi(); |
| WiFiEndpointRefPtr endpoint; |
| DBus::Path bss_path; |
| WiFiServiceRefPtr service( |
| SetupConnectedService(DBus::Path(), &endpoint, &bss_path)); |
| EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint))) |
| .WillOnce(Return(reinterpret_cast<WiFiService *>(NULL))); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()).Times(0); |
| RemoveBSS(bss_path); |
| } |
| |
| TEST_F(WiFiMainTest, ReconnectPreservesDBusPath) { |
| StartWiFi(); |
| DBus::Path kPath = "/test/path"; |
| WiFiServiceRefPtr service(SetupConnectedService(kPath, NULL, NULL)); |
| |
| // Return the service to a connectable state. |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| InitiateDisconnect(service); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| |
| // Complete the disconnection by reporting a BSS change. |
| ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull); |
| |
| // A second connection attempt should remember the DBus path associated |
| // with this service. |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), AddNetwork(_)).Times(0); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), SelectNetwork(kPath)); |
| InitiateConnect(service); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectPendingService) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service( |
| SetupConnectingService(DBus::Path(), NULL, NULL)); |
| EXPECT_TRUE(GetPendingService() == service.get()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| EXPECT_CALL(*service, SetState(Service::kStateIdle)).Times(AtLeast(1)); |
| InitiateDisconnect(service); |
| Mock::VerifyAndClearExpectations(service.get()); |
| EXPECT_TRUE(GetPendingService() == NULL); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectPendingServiceWithCurrent) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service0( |
| SetupConnectedService(DBus::Path(), NULL, NULL)); |
| EXPECT_EQ(service0, GetCurrentService()); |
| EXPECT_EQ(NULL, GetPendingService().get()); |
| |
| // We don't explicitly call Disconnect() while transitioning to a new |
| // service. Instead, we use the side-effect of SelectNetwork (verified in |
| // SetupConnectingService). |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()).Times(0); |
| MockWiFiServiceRefPtr service1( |
| SetupConnectingService("/new/path", NULL, NULL)); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| |
| EXPECT_EQ(service0, GetCurrentService()); |
| EXPECT_EQ(service1, GetPendingService()); |
| EXPECT_CALL(*service1, SetState(Service::kStateIdle)).Times(AtLeast(1)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| InitiateDisconnect(service1); |
| Mock::VerifyAndClearExpectations(service1.get()); |
| |
| // |current_service_| will be unchanged until supplicant signals |
| // that CurrentBSS has changed. |
| EXPECT_EQ(service0, GetCurrentService()); |
| // |pending_service_| is updated immediately. |
| EXPECT_EQ(NULL, GetPendingService().get()); |
| EXPECT_TRUE(GetPendingTimeout().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectCurrentService) { |
| StartWiFi(); |
| ::DBus::Path kPath("/fake/path"); |
| MockWiFiServiceRefPtr service(SetupConnectedService(kPath, NULL, NULL)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| InitiateDisconnect(service); |
| |
| // |current_service_| should not change until supplicant reports |
| // a BSS change. |
| EXPECT_EQ(service, GetCurrentService()); |
| |
| // Expect that the entry associated with this network will be disabled. |
| MockSupplicantNetworkProxy *network_proxy = CreateSupplicantNetworkProxy(); |
| EXPECT_CALL(*proxy_factory(), CreateSupplicantNetworkProxy( |
| kPath, WPASupplicant::kDBusAddr)) |
| .WillOnce(Return(network_proxy)); |
| EXPECT_CALL(*network_proxy, SetEnabled(false)); |
| EXPECT_CALL(*eap_state_handler_, Reset()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(kPath)).Times(0); |
| ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull); |
| EXPECT_EQ(NULL, GetCurrentService().get()); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectCurrentServiceWithErrors) { |
| StartWiFi(); |
| DBus::Path kPath("/fake/path"); |
| WiFiServiceRefPtr service(SetupConnectedService(kPath, NULL, NULL)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()) |
| .WillOnce(InvokeWithoutArgs(this, (&WiFiMainTest::ThrowDBusError))); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(kPath)).Times(1); |
| InitiateDisconnect(service); |
| |
| // We may sometimes fail to disconnect via supplicant, and we patch up some |
| // state when this happens. |
| EXPECT_EQ(NULL, GetCurrentService().get()); |
| EXPECT_EQ(NULL, wifi()->selected_service().get()); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectCurrentServiceWithPending) { |
| StartWiFi(); |
| WiFiServiceRefPtr service0(SetupConnectedService(DBus::Path(), NULL, NULL)); |
| WiFiServiceRefPtr service1(SetupConnectingService(DBus::Path(), NULL, NULL)); |
| EXPECT_EQ(service0, GetCurrentService()); |
| EXPECT_EQ(service1, GetPendingService()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()).Times(0); |
| InitiateDisconnect(service0); |
| |
| EXPECT_EQ(service0, GetCurrentService()); |
| EXPECT_EQ(service1, GetPendingService()); |
| EXPECT_FALSE(GetPendingTimeout().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, TimeoutPendingServiceWithEndpoints) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(10); |
| |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| StartWiFi(); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(_, _)).Times(AnyNumber()); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, true)); |
| dispatcher_.DispatchPendingEvents(); |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive); |
| const base::CancelableClosure &pending_timeout = GetPendingTimeout(); |
| EXPECT_TRUE(pending_timeout.IsCancelled()); |
| MockWiFiServiceRefPtr service( |
| SetupConnectingService(DBus::Path(), NULL, NULL)); |
| EXPECT_FALSE(pending_timeout.IsCancelled()); |
| EXPECT_EQ(service, GetPendingService()); |
| // Simulate a service with a wifi_ reference calling DisconnectFrom(). |
| EXPECT_CALL(*service, DisconnectWithFailure(Service::kFailureOutOfRange, _)) |
| .WillOnce(InvokeWithoutArgs(this, &WiFiObjectTest::ResetPendingService)); |
| EXPECT_CALL(*service, HasEndpoints()).Times(0); |
| // DisconnectFrom() should not be called directly from WiFi. |
| EXPECT_CALL(*service, SetState(Service::kStateIdle)).Times(0); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()).Times(0); |
| |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, false)); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, |
| HasSubstr("-> PROGRESSIVE_FINISHED_NOCONNECTION"))); |
| pending_timeout.callback().Run(); |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| Mock::VerifyAndClearExpectations(service); |
| |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| } |
| |
| TEST_F(WiFiMainTest, TimeoutPendingServiceWithoutEndpoints) { |
| StartWiFi(); |
| const base::CancelableClosure &pending_timeout = GetPendingTimeout(); |
| EXPECT_TRUE(pending_timeout.IsCancelled()); |
| MockWiFiServiceRefPtr service( |
| SetupConnectingService(DBus::Path(), NULL, NULL)); |
| EXPECT_FALSE(pending_timeout.IsCancelled()); |
| EXPECT_EQ(service, GetPendingService()); |
| // We expect the service to get a disconnect call, but in this scenario |
| // the service does nothing. |
| EXPECT_CALL(*service, DisconnectWithFailure(Service::kFailureOutOfRange, _)); |
| EXPECT_CALL(*service, HasEndpoints()).WillOnce(Return(false)); |
| // DisconnectFrom() should be called directly from WiFi. |
| EXPECT_CALL(*service, SetState(Service::kStateIdle)).Times(AtLeast(1)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| pending_timeout.callback().Run(); |
| EXPECT_EQ(NULL, GetPendingService().get()); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectInvalidService) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service; |
| MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, NULL, &service); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()).Times(0); |
| InitiateDisconnect(service); |
| } |
| |
| TEST_F(WiFiMainTest, DisconnectCurrentServiceFailure) { |
| StartWiFi(); |
| DBus::Path kPath("/fake/path"); |
| WiFiServiceRefPtr service(SetupConnectedService(kPath, NULL, NULL)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()) |
| .WillRepeatedly(Throw( |
| DBus::Error( |
| "fi.w1.wpa_supplicant1.NotConnected", |
| "test threw fi.w1.wpa_supplicant1.NotConnected"))); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(kPath)); |
| InitiateDisconnect(service); |
| EXPECT_EQ(NULL, GetCurrentService().get()); |
| } |
| |
| TEST_F(WiFiMainTest, Stop) { |
| StartWiFi(); |
| WiFiEndpointRefPtr endpoint0; |
| ::DBus::Path kPath("/fake/path"); |
| WiFiServiceRefPtr service0(SetupConnectedService(kPath, &endpoint0, NULL)); |
| WiFiEndpointRefPtr endpoint1; |
| MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, &endpoint1, NULL); |
| |
| EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint0))) |
| .WillOnce(Return(reinterpret_cast<WiFiService *>(NULL))); |
| EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint1))) |
| .WillOnce(Return(reinterpret_cast<WiFiService *>(NULL))); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(kPath)).Times(1); |
| StopWiFi(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| EXPECT_FALSE(wifi()->weak_ptr_factory_.HasWeakPtrs()); |
| } |
| |
| TEST_F(WiFiMainTest, StopWhileConnected) { |
| StartWiFi(); |
| WiFiEndpointRefPtr endpoint; |
| WiFiServiceRefPtr service( |
| SetupConnectedService(DBus::Path(), &endpoint, NULL)); |
| scoped_ptr<EndpointRemovalHandler> handler( |
| MakeEndpointRemovalHandler(service)); |
| EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint))) |
| .WillOnce(Invoke(handler.get(), |
| &EndpointRemovalHandler::OnEndpointRemoved)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| StopWiFi(); |
| EXPECT_TRUE(GetCurrentService() == NULL); |
| } |
| |
| TEST_F(WiFiMainTest, ReconnectTimer) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service( |
| SetupConnectedService(DBus::Path(), NULL, NULL)); |
| EXPECT_CALL(*service, IsConnected()).WillRepeatedly(Return(true)); |
| EXPECT_TRUE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportStateChanged(WPASupplicant::kInterfaceStateDisconnected); |
| EXPECT_FALSE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportStateChanged(WPASupplicant::kInterfaceStateCompleted); |
| EXPECT_TRUE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportStateChanged(WPASupplicant::kInterfaceStateDisconnected); |
| EXPECT_FALSE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportCurrentBSSChanged(kBSSName); |
| EXPECT_TRUE(GetReconnectTimeoutCallback().IsCancelled()); |
| ReportStateChanged(WPASupplicant::kInterfaceStateDisconnected); |
| EXPECT_FALSE(GetReconnectTimeoutCallback().IsCancelled()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| GetReconnectTimeoutCallback().callback().Run(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| EXPECT_TRUE(GetReconnectTimeoutCallback().IsCancelled()); |
| } |
| |
| |
| MATCHER_P(HasHiddenSSID_FullScan, ssid, "") { |
| map<string, DBus::Variant>::const_iterator it = |
| arg.find(WPASupplicant::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 && ssids[0] == ssid && ssids[1].empty(); |
| } |
| |
| MATCHER(HasNoHiddenSSID_FullScan, "") { |
| map<string, DBus::Variant>::const_iterator it = |
| arg.find(WPASupplicant::kPropertyScanSSIDs); |
| return it == arg.end(); |
| } |
| |
| TEST_F(WiFiMainTest, ScanHidden_FullScan) { |
| EnableFullScan(); |
| vector<uint8_t>kSSID(1, 'a'); |
| ByteArrays ssids; |
| ssids.push_back(kSSID); |
| |
| StartWiFi(); |
| EXPECT_CALL(*wifi_provider(), GetHiddenSSIDList()).WillOnce(Return(ssids)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), |
| Scan(HasHiddenSSID_FullScan(kSSID))); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| // This test is slightly different from the test in scan_session_unittest.cc |
| // because this tests the piece of WiFi that builds the SSID list. |
| TEST_F(WiFiMainTest, ScanHidden) { |
| // Clear the Mock ScanSession because hidden SSIDs are added when wifi |
| // instantiates a new ScanSession (and it won't instantiate a new ScanSession |
| // if there's already one there). |
| ClearScanSession(); |
| vector<uint8_t>kSSID(1, 'a'); |
| ByteArrays ssids; |
| ssids.push_back(kSSID); |
| |
| EXPECT_CALL(netlink_manager_, SendNl80211Message( |
| IsNl80211Command(kNl80211FamilyId, NL80211_CMD_GET_WIPHY), _, _)); |
| EXPECT_CALL(*wifi_provider(), GetHiddenSSIDList()).WillOnce(Return(ssids)); |
| StartWiFi(); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message(HasHiddenSSID(kNl80211FamilyId), _, _)); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ScanNoHidden_FullScan) { |
| EnableFullScan(); |
| StartWiFi(); |
| EXPECT_CALL(*wifi_provider(), GetHiddenSSIDList()) |
| .WillOnce(Return(ByteArrays())); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(HasNoHiddenSSID_FullScan())); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| // This test is slightly different from the test in scan_session_unittest.cc |
| // because this tests the piece of WiFi that builds the SSID list. |
| TEST_F(WiFiMainTest, ScanNoHidden) { |
| // Clear the Mock ScanSession because hidden SSIDs are added when wifi |
| // instantiates a new ScanSession (and it won't instantiate a new ScanSession |
| // if there's already one there). |
| ClearScanSession(); |
| EXPECT_CALL(netlink_manager_, SendNl80211Message( |
| IsNl80211Command(kNl80211FamilyId, NL80211_CMD_GET_WIPHY), _, _)); |
| EXPECT_CALL(*wifi_provider(), GetHiddenSSIDList()) |
| .WillOnce(Return(ByteArrays())); |
| StartWiFi(); |
| EXPECT_CALL(netlink_manager_, |
| SendNl80211Message(HasNoHiddenSSID(kNl80211FamilyId), _, _)); |
| 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(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| StartWiFi(); |
| StopWiFi(); |
| // A scan is queued when WiFi resumes. |
| OnAfterResume(); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ProgressiveScanFound) { |
| // Set min & max scan frequency count to 1 so each scan will be of a single |
| // frequency. |
| SetScanSize(1, 1); |
| |
| // Do the first scan (finds nothing). |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(_, _)).Times(AnyNumber()); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, true)); |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive); |
| ReportScanDoneKeepScanSession(); |
| |
| // Do the second scan (connects afterwards). |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| dispatcher_.DispatchPendingEvents(); |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive); |
| ReportScanDoneKeepScanSession(); |
| |
| // Connect after second scan. |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| SetPendingService(service); |
| |
| // Verify that the third scan aborts and there is no further scan. |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, EndsWith( |
| "Ignoring scan request while connecting to an AP."))).Times(1); |
| EXPECT_CALL(*metrics(), NotifyDeviceScanFinished(_)); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, false)); |
| dispatcher_.DispatchPendingEvents(); |
| VerifyScanState(WiFi::kScanConnecting, WiFi::kScanMethodProgressive); |
| } |
| |
| TEST_F(WiFiMainTest, ProgressiveScanNotFound) { |
| // Set min & max scan frequency count to 1 so each scan will be of a single |
| // frequency. |
| SetScanSize(1, 1); |
| |
| // Do the first scan (finds nothing). |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); // Launch ProgressiveScanTask |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive); |
| ReportScanDoneKeepScanSession(); |
| |
| // Do the second scan (finds nothing). |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| dispatcher_.DispatchPendingEvents(); |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive); |
| ReportScanDoneKeepScanSession(); |
| |
| // Do the third scan. After (simulated) exhausting of search frequencies, |
| // verify that this scan uses supplicant rather than internal (progressive) |
| // scan. |
| EXPECT_CALL(*scan_session_, HasMoreFrequencies()).WillOnce(Return(false)); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| dispatcher_.DispatchPendingEvents(); |
| VerifyScanState(WiFi::kScanScanning, |
| WiFi::kScanMethodProgressiveFinishedToFull); |
| |
| // And verify that ScanDone reports a complete scan (i.e., the |
| // wifi_::scan_session_ has truly been cleared). |
| EXPECT_CALL(*metrics(), NotifyDeviceScanFinished(_)); |
| ReportScanDoneKeepScanSession(); |
| dispatcher_.DispatchPendingEvents(); // Launch UpdateScanStateAfterScanDone |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| } |
| |
| TEST_F(WiFiMainTest, ProgressiveScanError) { |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| ClearScanSession(); // Clear Mock ScanSession to get an actual ScanSession. |
| StartWiFi(); |
| |
| // This should call |Scan| which posts |ScanTask| |
| NewScanResultsMessage not_supposed_to_get_this_message; |
| OnTriggerScanResponse(not_supposed_to_get_this_message); |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressiveErrorToFull); |
| |
| EXPECT_TRUE(IsScanSessionNull()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(1); |
| dispatcher_.DispatchPendingEvents(); |
| |
| ReportScanDoneKeepScanSession(); |
| dispatcher_.DispatchPendingEvents(); // Launch UpdateScanStateAfterScanDone |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| } |
| |
| 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(WPASupplicant::kInterfaceStateScanning); |
| EXPECT_EQ(WPASupplicant::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(WPASupplicant::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(WPASupplicant::kInterfaceStateCompleted); |
| ReportStateChanged(WPASupplicant::kInterfaceStateAuthenticating); |
| EXPECT_EQ(WPASupplicant::kInterfaceStateAuthenticating, |
| GetSupplicantState()); |
| // Verify expectations now, because WiFi may report other state changes |
| // when WiFi is Stop()-ed (during TearDown()). |
| Mock::VerifyAndClearExpectations(service); |
| EXPECT_CALL(*service, SetState(_)).Times(AnyNumber()); |
| } |
| |
| TEST_F(WiFiMainTest, ConnectToServiceWithoutRecentIssues) { |
| MockSupplicantProcessProxy *process_proxy = supplicant_process_proxy_.get(); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| EXPECT_CALL(*process_proxy, GetDebugLevel()).Times(0); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(_)).Times(0); |
| EXPECT_CALL(*service.get(), HasRecentConnectionIssues()) |
| .WillOnce(Return(false)); |
| InitiateConnect(service); |
| } |
| |
| TEST_F(WiFiMainTest, ConnectToServiceWithRecentIssues) { |
| // Turn of WiFi debugging, so the only reason we will turn on supplicant |
| // debugging will be to debug a problematic connection. |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| |
| MockSupplicantProcessProxy *process_proxy = supplicant_process_proxy_.get(); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| EXPECT_CALL(*process_proxy, GetDebugLevel()) |
| .WillOnce(Return(WPASupplicant::kDebugLevelInfo)); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(WPASupplicant::kDebugLevelDebug)) |
| .Times(1); |
| EXPECT_CALL(*service.get(), HasRecentConnectionIssues()) |
| .WillOnce(Return(true)); |
| InitiateConnect(service); |
| Mock::VerifyAndClearExpectations(process_proxy); |
| |
| SetPendingService(NULL); |
| SetCurrentService(service); |
| |
| // When we disconnect from the troubled service, we should reduce the |
| // level of supplciant debugging. |
| EXPECT_CALL(*process_proxy, GetDebugLevel()) |
| .WillOnce(Return(WPASupplicant::kDebugLevelDebug)); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(WPASupplicant::kDebugLevelInfo)) |
| .Times(1); |
| ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull); |
| } |
| |
| TEST_F(WiFiMainTest, CurrentBSSChangeConnectedToDisconnected) { |
| StartWiFi(); |
| WiFiEndpointRefPtr endpoint; |
| MockWiFiServiceRefPtr service = |
| SetupConnectedService(DBus::Path(), &endpoint, NULL); |
| |
| EXPECT_CALL(*service, SetState(Service::kStateIdle)); |
| EXPECT_CALL(*service, SetFailureSilent(Service::kFailureUnknown)); |
| ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull); |
| EXPECT_EQ(NULL, GetCurrentService().get()); |
| EXPECT_EQ(NULL, GetPendingService().get()); |
| } |
| |
| TEST_F(WiFiMainTest, CurrentBSSChangeConnectedToConnectedNewService) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service0 = |
| SetupConnectedService(DBus::Path(), NULL, NULL); |
| MockWiFiServiceRefPtr service1; |
| ::DBus::Path bss_path1(MakeNewEndpointAndService( |
| 0, 0, kNetworkModeAdHoc, NULL, &service1)); |
| EXPECT_EQ(service0.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. |
| EXPECT_CALL(*service0, SetState(Service::kStateIdle)).Times(AtLeast(1)); |
| ReportCurrentBSSChanged(bss_path1); |
| EXPECT_CALL(*service1, SetState(Service::kStateConfiguring)); |
| ReportStateChanged(WPASupplicant::kInterfaceStateCompleted); |
| EXPECT_EQ(service1.get(), GetCurrentService().get()); |
| Mock::VerifyAndClearExpectations(service0); |
| Mock::VerifyAndClearExpectations(service1); |
| } |
| |
| TEST_F(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint) { |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive); |
| |
| MockWiFiServiceRefPtr service = |
| SetupConnectedService(DBus::Path(), NULL, NULL); |
| WiFiEndpointRefPtr endpoint; |
| ::DBus::Path bss_path = |
| AddEndpointToService(service, 0, 0, kNetworkModeAdHoc, &endpoint); |
| EXPECT_CALL(*service, NotifyCurrentEndpoint(EndpointMatch(endpoint))); |
| ReportCurrentBSSChanged(bss_path); |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| } |
| |
| TEST_F(WiFiMainTest, NewConnectPreemptsPending) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service0( |
| SetupConnectingService(DBus::Path(), NULL, NULL)); |
| EXPECT_EQ(service0.get(), GetPendingService().get()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()); |
| MockWiFiServiceRefPtr service1( |
| SetupConnectingService(DBus::Path(), NULL, NULL)); |
| EXPECT_EQ(service1.get(), GetPendingService().get()); |
| EXPECT_EQ(NULL, GetCurrentService().get()); |
| } |
| |
| TEST_F(WiFiMainTest, IsIdle) { |
| StartWiFi(); |
| EXPECT_TRUE(wifi()->IsIdle()); |
| MockWiFiServiceRefPtr service( |
| SetupConnectingService(DBus::Path(), NULL, NULL)); |
| EXPECT_FALSE(wifi()->IsIdle()); |
| } |
| |
| MATCHER_P(WiFiAddedArgs, bgscan, "") { |
| return ContainsKey(arg, WPASupplicant::kNetworkPropertyScanSSID) && |
| ContainsKey(arg, WPASupplicant::kNetworkPropertyBgscan) == bgscan; |
| } |
| |
| TEST_F(WiFiMainTest, AddNetworkArgs) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service; |
| MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, NULL, &service); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), AddNetwork(WiFiAddedArgs(true))); |
| EXPECT_TRUE(SetBgscanMethod(WPASupplicant::kNetworkBgscanMethodSimple)); |
| InitiateConnect(service); |
| } |
| |
| TEST_F(WiFiMainTest, AddNetworkArgsNoBgscan) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service; |
| MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, NULL, &service); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), AddNetwork(WiFiAddedArgs(false))); |
| InitiateConnect(service); |
| } |
| |
| TEST_F(WiFiMainTest, AppendBgscan) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| { |
| // 1 endpoint, default bgscan method -- background scan disabled. |
| std::map<std::string, DBus::Variant> params; |
| EXPECT_CALL(*service, GetEndpointCount()).WillOnce(Return(1)); |
| AppendBgscan(service, ¶ms); |
| Mock::VerifyAndClearExpectations(service); |
| EXPECT_FALSE(ContainsKey(params, WPASupplicant::kNetworkPropertyBgscan)); |
| } |
| { |
| // 2 endpoints, default bgscan method -- background scan frequency reduced. |
| map<string, DBus::Variant> params; |
| EXPECT_CALL(*service, GetEndpointCount()).WillOnce(Return(2)); |
| AppendBgscan(service, ¶ms); |
| Mock::VerifyAndClearExpectations(service); |
| string config_string; |
| EXPECT_TRUE( |
| DBusProperties::GetString(params, |
| WPASupplicant::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(WPASupplicant::kNetworkBgscanMethodSimple)); |
| std::map<std::string, DBus::Variant> params; |
| EXPECT_CALL(*service, GetEndpointCount()).Times(0); |
| AppendBgscan(service, ¶ms); |
| Mock::VerifyAndClearExpectations(service); |
| string config_string; |
| EXPECT_TRUE( |
| DBusProperties::GetString(params, |
| WPASupplicant::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(WPASupplicant::kNetworkBgscanMethodNone)); |
| std::map<std::string, DBus::Variant> params; |
| EXPECT_CALL(*service, GetEndpointCount()).Times(0); |
| AppendBgscan(service.get(), ¶ms); |
| Mock::VerifyAndClearExpectations(service); |
| string config_string; |
| EXPECT_FALSE( |
| DBusProperties::GetString(params, |
| WPASupplicant::kNetworkPropertyBgscan, |
| &config_string)); |
| } |
| } |
| |
| TEST_F(WiFiMainTest, StateAndIPIgnoreLinkEvent) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service( |
| SetupConnectingService(DBus::Path(), NULL, NULL)); |
| 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); |
| } |
| |
| TEST_F(WiFiMainTest, SupplicantCompletedAlreadyConnected) { |
| StartWiFi(); |
| MockWiFiServiceRefPtr service( |
| SetupConnectedService(DBus::Path(), NULL, NULL)); |
| Mock::VerifyAndClearExpectations(dhcp_config_.get()); |
| EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(0); |
| // Simulate a rekeying event from the AP. These show as transitions from |
| // completed->completed from wpa_supplicant. |
| ReportStateChanged(WPASupplicant::kInterfaceStateCompleted); |
| // When we get an IP, WiFi should enable high bitrates on the interface again. |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), EnableHighBitrates()).Times(1); |
| EXPECT_CALL(*manager(), device_info()).WillOnce(Return(device_info())); |
| string portal_url; |
| EXPECT_CALL(*manager(), GetPortalCheckURL()).WillOnce(ReturnRef(portal_url)); |
| ReportIPConfigComplete(); |
| // Similarly, rekeying events after we have an IP don't trigger L3 |
| // configuration. However, we treat all transitions to completed as potential |
| // reassociations, so we will reenable high rates again here. |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| EXPECT_CALL(*service, IsConnected()).WillOnce(Return(true)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), EnableHighBitrates()).Times(1); |
| ReportStateChanged(WPASupplicant::kInterfaceStateCompleted); |
| } |
| |
| TEST_F(WiFiMainTest, BSSAddedCreatesBSSProxy) { |
| // 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. |
| // Get the pointer before we transfer ownership. |
| MockSupplicantBSSProxy *proxy = supplicant_bss_proxy_.get(); |
| EXPECT_CALL(*proxy, Die()); |
| StartWiFi(); |
| DBus::Path bss_path( |
| MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, NULL, NULL)); |
| EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(_)) |
| .WillOnce(Return(reinterpret_cast<WiFiService *>(NULL))); |
| RemoveBSS(bss_path); |
| // 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}; |
| |
| StartWiFi(); |
| |
| EXPECT_CALL(time_, GetTimeMonotonic(_)) |
| .WillOnce(DoAll(SetArgumentPointee<0>(resume_time), Return(0))) |
| .WillOnce(DoAll(SetArgumentPointee<0>(scan_done_time), Return(0))); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), |
| FlushBSS(WiFi::kMaxBSSResumeAgeSeconds + 5)); |
| OnAfterResume(); |
| ReportScanDone(); |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerIdle_FullScan) { |
| EnableFullScan(); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| ReportScanDone(); |
| CancelScanTimer(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| FireScanTimer(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); // Automatically re-armed. |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerIdle) { |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| ReportScanDone(); |
| CancelScanTimer(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| 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); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| FireScanTimer(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); // Automatically re-armed. |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerConnecting) { |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| MockWiFiServiceRefPtr service = |
| SetupConnectingService(DBus::Path(), NULL, NULL); |
| CancelScanTimer(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| FireScanTimer(); |
| dispatcher_.DispatchPendingEvents(); |
| EXPECT_FALSE(GetScanTimer().IsCancelled()); // Automatically re-armed. |
| } |
| |
| TEST_F(WiFiMainTest, ScanTimerReconfigured) { |
| StartWiFi(); |
| CancelScanTimer(); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| |
| SetScanInterval(1, NULL); |
| 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, NULL); |
| EXPECT_TRUE(GetScanTimer().IsCancelled()); |
| } |
| |
| TEST_F(WiFiMainTest, ScanOnDisconnectWithHidden_FullScan) { |
| EnableFullScan(); |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| SetupConnectedService(DBus::Path(), NULL, NULL); |
| vector<uint8_t>kSSID(1, 'a'); |
| ByteArrays ssids; |
| ssids.push_back(kSSID); |
| EXPECT_CALL(*wifi_provider(), GetHiddenSSIDList()) |
| .WillRepeatedly(Return(ssids)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), |
| Scan(HasHiddenSSID_FullScan(kSSID))); |
| ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, ScanOnDisconnectWithHidden) { |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| ReportScanDone(); |
| SetupConnectedService(DBus::Path(), NULL, NULL); |
| vector<uint8_t>kSSID(1, 'a'); |
| ByteArrays ssids; |
| ssids.push_back(kSSID); |
| EXPECT_CALL(*wifi_provider(), GetHiddenSSIDList()) |
| .WillRepeatedly(Return(ssids)); |
| EXPECT_CALL(*scan_session_, InitiateScan()); |
| ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull); |
| dispatcher_.DispatchPendingEvents(); |
| } |
| |
| TEST_F(WiFiMainTest, NoScanOnDisconnectWithoutHidden) { |
| StartWiFi(); |
| dispatcher_.DispatchPendingEvents(); |
| SetupConnectedService(DBus::Path(), NULL, NULL); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0); |
| EXPECT_CALL(*scan_session_, InitiateScan()).Times(0); |
| EXPECT_CALL(*wifi_provider(), GetHiddenSSIDList()) |
| .WillRepeatedly(Return(ByteArrays())); |
| ReportCurrentBSSChanged(WPASupplicant::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(); |
| Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy()); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Reassociate()).Times(0); |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, |
| EndsWith("Cannot reassociate."))).Times(1); |
| OnLinkMonitorFailure(); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsOpen) { |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityNone); |
| ReportStateChanged(WPASupplicant::kInterfaceState4WayHandshake); |
| EXPECT_FALSE(service->has_ever_connected()); |
| EXPECT_FALSE(SuspectCredentials(*service, NULL)); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsWPANeverConnected) { |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityWpa); |
| ReportStateChanged(WPASupplicant::kInterfaceState4WayHandshake); |
| EXPECT_FALSE(service->has_ever_connected()); |
| Service::ConnectFailure failure; |
| EXPECT_TRUE(SuspectCredentials(*service, &failure)); |
| EXPECT_EQ(Service::kFailureBadPassphrase, failure); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsWPAPreviouslyConnected) { |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityWpa); |
| ReportStateChanged(WPASupplicant::kInterfaceState4WayHandshake); |
| service->has_ever_connected_ = true; |
| EXPECT_FALSE(SuspectCredentials(*service, NULL)); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsEAPInProgress) { |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurity8021x); |
| EXPECT_CALL(*eap_state_handler_, is_eap_in_progress()) |
| .WillOnce(Return(false)) |
| .WillOnce(Return(true)) |
| .WillOnce(Return(false)) |
| .WillOnce(Return(true)); |
| service->has_ever_connected_ = false; |
| EXPECT_FALSE(SuspectCredentials(*service, NULL)); |
| Service::ConnectFailure failure; |
| EXPECT_TRUE(SuspectCredentials(*service, &failure)); |
| EXPECT_EQ(Service::kFailureEAPAuthentication, failure); |
| service->has_ever_connected_ = true; |
| EXPECT_FALSE(SuspectCredentials(*service, NULL)); |
| EXPECT_FALSE(SuspectCredentials(*service, NULL)); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsYieldFailureWPA) { |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurityWpa); |
| SetPendingService(service); |
| ReportStateChanged(WPASupplicant::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); |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, |
| EndsWith(flimflam::kErrorBadPassphrase))); |
| ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull); |
| } |
| |
| TEST_F(WiFiMainTest, SuspectCredentialsYieldFailureEAP) { |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurity8021x); |
| SetCurrentService(service); |
| EXPECT_FALSE(service->has_ever_connected()); |
| |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(*service, SetFailureSilent(_)).Times(0); |
| EXPECT_CALL(*service, SetState(_)).Times(0); |
| // Ensure that we retrieve is_eap_in_progress() before resetting the |
| // EAP handler's state. |
| InSequence seq; |
| EXPECT_CALL(*eap_state_handler_, is_eap_in_progress()) |
| .WillOnce(Return(true)); |
| EXPECT_CALL(*service, SetFailure(Service::kFailureEAPAuthentication)); |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, |
| EndsWith(shill::kErrorEapAuthenticationFailed))); |
| EXPECT_CALL(*eap_state_handler_, Reset()); |
| ReportCurrentBSSChanged(WPASupplicant::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()); |
| StartWiFi(); |
| SetupConnectedService(DBus::Path(), NULL, NULL); |
| 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[WPASupplicant::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[WPASupplicant::kInterfacePropertySubject].writer() |
| .append_string(kSubject.c_str()); |
| EXPECT_CALL(*service, AddEAPCertification(kSubject, kDepth)).Times(1); |
| ReportCertification(args); |
| } |
| |
| TEST_F(WiFiMainTest, EAPEvent) { |
| ScopedMockLog log; |
| EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith("no current service."))); |
| EXPECT_CALL(*eap_state_handler_, ParseStatus(_, _, _)).Times(0); |
| const string kEAPStatus("eap-status"); |
| const string kEAPParameter("eap-parameter"); |
| ReportEAPEvent(kEAPStatus, kEAPParameter); |
| Mock::VerifyAndClearExpectations(&log); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| |
| MockWiFiServiceRefPtr service = MakeMockService(flimflam::kSecurity8021x); |
| EXPECT_CALL(*service, SetFailure(_)).Times(0); |
| EXPECT_CALL(*eap_state_handler_, ParseStatus(kEAPStatus, kEAPParameter, _)); |
| SetCurrentService(service); |
| ReportEAPEvent(kEAPStatus, kEAPParameter); |
| Mock::VerifyAndClearExpectations(service); |
| Mock::VerifyAndClearExpectations(eap_state_handler_); |
| |
| EXPECT_CALL(*eap_state_handler_, ParseStatus(kEAPStatus, kEAPParameter, _)) |
| .WillOnce(DoAll(SetArgumentPointee<2>(Service::kFailureOutOfRange), |
| Return(false))); |
| EXPECT_CALL(*service, DisconnectWithFailure(Service::kFailureOutOfRange, _)); |
| ReportEAPEvent(kEAPStatus, kEAPParameter); |
| } |
| |
| 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(); |
| } |
| |
| TEST_F(WiFiMainTest, VerifyPaths) { |
| string path(WPASupplicant::kSupplicantConfPath); |
| TrimString(path, FilePath::kSeparators, &path); |
| EXPECT_TRUE(file_util::PathExists(FilePath(SYSROOT).Append(path))); |
| } |
| |
| struct BSS { |
| string bsspath; |
| string ssid; |
| string bssid; |
| int16_t signal_strength; |
| uint16 frequency; |
| const char* mode; |
| }; |
| |
| TEST_F(WiFiMainTest, GetGeolocationObjects) { |
| BSS bsses[] = { |
| {"bssid1", "ssid1", "00:00:00:00:00:00", 5, Metrics::kWiFiFrequency2412, |
| kNetworkModeInfrastructure}, |
| {"bssid2", "ssid2", "01:00:00:00:00:00", 30, Metrics::kWiFiFrequency5170, |
| kNetworkModeInfrastructure}, |
| // Same SSID but different BSSID is an additional geolocation object. |
| {"bssid3", "ssid1", "02:00:00:00:00:00", 100, 0, |
| kNetworkModeInfrastructure} |
| }; |
| StartWiFi(); |
| vector<GeolocationInfo> objects; |
| EXPECT_EQ(objects.size(), 0); |
| |
| for (size_t i = 0; i < arraysize(bsses); ++i) { |
| ReportBSS(bsses[i].bsspath, bsses[i].ssid, bsses[i].bssid, |
| bsses[i].signal_strength, bsses[i].frequency, bsses[i].mode); |
| objects = wifi()->GetGeolocationObjects(); |
| EXPECT_EQ(objects.size(), i + 1); |
| |
| GeolocationInfo expected_info; |
| expected_info.AddField(kGeoMacAddressProperty, bsses[i].bssid); |
| expected_info.AddField(kGeoSignalStrengthProperty, |
| StringPrintf("%d", bsses[i].signal_strength)); |
| expected_info.AddField(kGeoChannelProperty, StringPrintf( |
| "%d", Metrics::WiFiFrequencyToChannel(bsses[i].frequency))); |
| EXPECT_TRUE(objects[i].Equals(expected_info)); |
| } |
| } |
| |
| TEST_F(WiFiMainTest, SetSupplicantDebugLevel) { |
| MockSupplicantProcessProxy *process_proxy = supplicant_process_proxy_.get(); |
| |
| // With WiFi not yet started, nothing interesting (including a crash) should |
| // happen. |
| EXPECT_CALL(*process_proxy, GetDebugLevel()).Times(0); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(_)).Times(0); |
| ReportWiFiDebugScopeChanged(true); |
| |
| // This unit test turns on WiFi debugging, so when we start WiFi, we should |
| // check but not set the debug level if we return the "debug" level. |
| EXPECT_CALL(*process_proxy, GetDebugLevel()) |
| .WillOnce(Return(WPASupplicant::kDebugLevelDebug)); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(_)).Times(0); |
| StartWiFi(); |
| Mock::VerifyAndClearExpectations(process_proxy); |
| |
| // If WiFi debugging is toggled and wpa_supplicant reports debugging |
| // is set to some unmanaged level, WiFi should leave it alone. |
| EXPECT_CALL(*process_proxy, GetDebugLevel()) |
| .WillOnce(Return(WPASupplicant::kDebugLevelError)) |
| .WillOnce(Return(WPASupplicant::kDebugLevelError)) |
| .WillOnce(Return(WPASupplicant::kDebugLevelExcessive)) |
| .WillOnce(Return(WPASupplicant::kDebugLevelExcessive)) |
| .WillOnce(Return(WPASupplicant::kDebugLevelMsgDump)) |
| .WillOnce(Return(WPASupplicant::kDebugLevelMsgDump)) |
| .WillOnce(Return(WPASupplicant::kDebugLevelWarning)) |
| .WillOnce(Return(WPASupplicant::kDebugLevelWarning)); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(_)).Times(0); |
| ReportWiFiDebugScopeChanged(true); |
| ReportWiFiDebugScopeChanged(false); |
| ReportWiFiDebugScopeChanged(true); |
| ReportWiFiDebugScopeChanged(false); |
| ReportWiFiDebugScopeChanged(true); |
| ReportWiFiDebugScopeChanged(false); |
| ReportWiFiDebugScopeChanged(true); |
| ReportWiFiDebugScopeChanged(false); |
| Mock::VerifyAndClearExpectations(process_proxy); |
| |
| // If WiFi debugging is turned off and wpa_supplicant reports debugging |
| // is turned on, WiFi should turn supplicant debugging off. |
| EXPECT_CALL(*process_proxy, GetDebugLevel()) |
| .WillOnce(Return(WPASupplicant::kDebugLevelDebug)); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(WPASupplicant::kDebugLevelInfo)) |
| .Times(1); |
| ReportWiFiDebugScopeChanged(false); |
| Mock::VerifyAndClearExpectations(process_proxy); |
| |
| // If WiFi debugging is turned on and wpa_supplicant reports debugging |
| // is turned off, WiFi should turn supplicant debugging on. |
| EXPECT_CALL(*process_proxy, GetDebugLevel()) |
| .WillOnce(Return(WPASupplicant::kDebugLevelInfo)); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(WPASupplicant::kDebugLevelDebug)) |
| .Times(1); |
| ReportWiFiDebugScopeChanged(true); |
| Mock::VerifyAndClearExpectations(process_proxy); |
| |
| // If WiFi debugging is already in the correct state, it should not be |
| // changed. |
| EXPECT_CALL(*process_proxy, GetDebugLevel()) |
| .WillOnce(Return(WPASupplicant::kDebugLevelDebug)) |
| .WillOnce(Return(WPASupplicant::kDebugLevelInfo)); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(_)).Times(0); |
| ReportWiFiDebugScopeChanged(true); |
| ReportWiFiDebugScopeChanged(false); |
| |
| // After WiFi is stopped, we shouldn't be calling the proxy. |
| EXPECT_CALL(*process_proxy, GetDebugLevel()).Times(0); |
| EXPECT_CALL(*process_proxy, SetDebugLevel(_)).Times(0); |
| StopWiFi(); |
| ReportWiFiDebugScopeChanged(true); |
| ReportWiFiDebugScopeChanged(false); |
| } |
| |
| TEST_F(WiFiMainTest, LogSSID) { |
| EXPECT_EQ("[SSID=]", WiFi::LogSSID("")); |
| EXPECT_EQ("[SSID=foo\\x5b\\x09\\x5dbar]", WiFi::LogSSID("foo[\t]bar")); |
| } |
| |
| // Custom property setters should return false, and make no changes, if |
| // the new value is the same as the old value. |
| TEST_F(WiFiMainTest, CustomSetterNoopChange) { |
| // SetBgscanShortInterval |
| { |
| Error error; |
| static const uint16 kKnownScanInterval = 4; |
| // Set to known value. |
| EXPECT_TRUE(SetBgscanShortInterval(kKnownScanInterval, &error)); |
| EXPECT_TRUE(error.IsSuccess()); |
| // Set to same value. |
| EXPECT_FALSE(SetBgscanShortInterval(kKnownScanInterval, &error)); |
| EXPECT_TRUE(error.IsSuccess()); |
| } |
| |
| // SetBgscanSignalThreshold |
| { |
| Error error; |
| static const int32 kKnownSignalThreshold = 4; |
| // Set to known value. |
| EXPECT_TRUE(SetBgscanSignalThreshold(kKnownSignalThreshold, &error)); |
| EXPECT_TRUE(error.IsSuccess()); |
| // Set to same value. |
| EXPECT_FALSE(SetBgscanSignalThreshold(kKnownSignalThreshold, &error)); |
| EXPECT_TRUE(error.IsSuccess()); |
| } |
| |
| // SetScanInterval |
| { |
| Error error; |
| EXPECT_FALSE(SetScanInterval(GetScanInterval(), &error)); |
| EXPECT_TRUE(error.IsSuccess()); |
| } |
| } |
| |
| // The following tests check the scan_state_ / scan_method_ state machine. |
| |
| TEST_F(WiFiMainTest, FullScanFindsNothing) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(10); |
| |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(_, _)).Times(AnyNumber()); |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| EnableFullScan(); |
| StartWiFi(); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, true)); |
| EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)); |
| dispatcher_.DispatchPendingEvents(); |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodFull); |
| |
| ReportScanDone(); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("FULL_NOCONNECTION ->"))); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, false)); |
| dispatcher_.DispatchPendingEvents(); // Launch UpdateScanStateAfterScanDone |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| } |
| |
| TEST_F(WiFiMainTest, FullScanConnectingToConnected) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(10); |
| |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(_, _)).Times(AnyNumber()); |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| EnableFullScan(); |
| StartWiFi(); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, true)); |
| dispatcher_.DispatchPendingEvents(); // Launch ScanTask |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodFull); |
| |
| // Setup a service and ask to connect to it. |
| WiFiEndpointRefPtr endpoint; |
| ::DBus::Path bss_path; |
| MockWiFiServiceRefPtr service = |
| SetupConnectingService(DBus::Path(), &endpoint, &bss_path); |
| |
| ReportScanDoneKeepScanSession(); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, false)); |
| dispatcher_.DispatchPendingEvents(); // Launch UpdateScanStateAfterScanDone |
| VerifyScanState(WiFi::kScanConnecting, WiFi::kScanMethodFull); |
| |
| // Complete the connection. |
| EXPECT_CALL(*service, NotifyCurrentEndpoint(EndpointMatch(endpoint))); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("-> FULL_CONNECTED"))); |
| ReportCurrentBSSChanged(bss_path); |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| } |
| |
| TEST_F(WiFiMainTest, ProgressiveScanConnectingToConnected) { |
| ScopedMockLog log; |
| ScopeLogger::GetInstance()->EnableScopesByName("wifi"); |
| ScopeLogger::GetInstance()->set_verbose_level(10); |
| |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(_, _)).Times(AnyNumber()); |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| StartWiFi(); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, true)); |
| dispatcher_.DispatchPendingEvents(); // Runs ProgressiveScanTask |
| VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive); |
| |
| // Setup a service and ask to connect to it. |
| WiFiEndpointRefPtr endpoint; |
| ::DBus::Path bss_path; |
| MockWiFiServiceRefPtr service = |
| SetupConnectingService(DBus::Path(), &endpoint, &bss_path); |
| |
| ReportScanDoneKeepScanSession(); |
| EXPECT_CALL(*adaptor_, EmitBoolChanged(flimflam::kScanningProperty, false)); |
| dispatcher_.DispatchPendingEvents(); // Launch ProgressiveScanTask |
| VerifyScanState(WiFi::kScanConnecting, WiFi::kScanMethodProgressive); |
| |
| // Complete the connection. |
| EXPECT_CALL(*service, NotifyCurrentEndpoint(EndpointMatch(endpoint))); |
| EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); |
| EXPECT_CALL(log, Log(_, _, HasSubstr("-> PROGRESSIVE_CONNECTED"))); |
| ReportCurrentBSSChanged(bss_path); |
| VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone); |
| |
| ScopeLogger::GetInstance()->set_verbose_level(0); |
| ScopeLogger::GetInstance()->EnableScopesByName("-wifi"); |
| } |
| |
| TEST_F(WiFiMainTest, ScanStateUma) { |
| EXPECT_CALL(*metrics(), SendEnumToUMA(Metrics::kMetricScanResult, _, _)). |
| Times(0); |
| SetScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive); |
| |
| EXPECT_CALL(*metrics(), SendEnumToUMA(Metrics::kMetricScanResult, _, _)); |
| SetScanState(WiFi::kScanConnected, WiFi::kScanMethodProgressive); |
| } |
| |
| } // namespace shill |