4646 lines
186 KiB
C++
4646 lines
186 KiB
C++
//
|
|
// Copyright (C) 2012 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include "shill/wifi/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/files/file_util.h>
|
|
#include <base/memory/ref_counted.h>
|
|
#include <base/strings/string_number_conversions.h>
|
|
#include <base/strings/string_split.h>
|
|
#include <base/strings/string_util.h>
|
|
#include <base/strings/stringprintf.h>
|
|
#if defined(__ANDROID__)
|
|
#include <dbus/service_constants.h>
|
|
#else
|
|
#include <chromeos/dbus/service_constants.h>
|
|
#endif // __ANDROID__
|
|
|
|
#include "shill/dhcp/mock_dhcp_config.h"
|
|
#include "shill/dhcp/mock_dhcp_provider.h"
|
|
#include "shill/error.h"
|
|
#include "shill/event_dispatcher.h"
|
|
#include "shill/geolocation_info.h"
|
|
#include "shill/ip_address_store.h"
|
|
#include "shill/key_value_store.h"
|
|
#include "shill/logging.h"
|
|
#include "shill/manager.h"
|
|
#include "shill/mock_adaptors.h"
|
|
#include "shill/mock_device.h"
|
|
#include "shill/mock_device_info.h"
|
|
#include "shill/mock_eap_credentials.h"
|
|
#include "shill/mock_event_dispatcher.h"
|
|
#include "shill/mock_ipconfig.h"
|
|
#include "shill/mock_link_monitor.h"
|
|
#include "shill/mock_log.h"
|
|
#include "shill/mock_manager.h"
|
|
#include "shill/mock_metrics.h"
|
|
#include "shill/mock_profile.h"
|
|
#include "shill/mock_store.h"
|
|
#include "shill/net/ieee80211.h"
|
|
#include "shill/net/ip_address.h"
|
|
#include "shill/net/mock_netlink_manager.h"
|
|
#include "shill/net/mock_rtnl_handler.h"
|
|
#include "shill/net/mock_time.h"
|
|
#include "shill/net/netlink_message_matchers.h"
|
|
#include "shill/net/netlink_packet.h"
|
|
#include "shill/net/nl80211_attribute.h"
|
|
#include "shill/net/nl80211_message.h"
|
|
#include "shill/nice_mock_control.h"
|
|
#include "shill/property_store_unittest.h"
|
|
#include "shill/supplicant/mock_supplicant_bss_proxy.h"
|
|
#include "shill/supplicant/mock_supplicant_eap_state_handler.h"
|
|
#include "shill/supplicant/mock_supplicant_interface_proxy.h"
|
|
#include "shill/supplicant/mock_supplicant_network_proxy.h"
|
|
#include "shill/supplicant/mock_supplicant_process_proxy.h"
|
|
#include "shill/supplicant/wpa_supplicant.h"
|
|
#include "shill/technology.h"
|
|
#include "shill/test_event_dispatcher.h"
|
|
#include "shill/testing.h"
|
|
#include "shill/wifi/mock_mac80211_monitor.h"
|
|
#include "shill/wifi/mock_scan_session.h"
|
|
#include "shill/wifi/mock_tdls_manager.h"
|
|
#include "shill/wifi/mock_wake_on_wifi.h"
|
|
#include "shill/wifi/mock_wifi_provider.h"
|
|
#include "shill/wifi/mock_wifi_service.h"
|
|
#include "shill/wifi/scan_session.h"
|
|
#include "shill/wifi/wake_on_wifi.h"
|
|
#include "shill/wifi/wifi_endpoint.h"
|
|
#include "shill/wifi/wifi_service.h"
|
|
|
|
using base::FilePath;
|
|
using base::StringPrintf;
|
|
using std::map;
|
|
using std::set;
|
|
using std::string;
|
|
using std::unique_ptr;
|
|
using std::vector;
|
|
using ::testing::_;
|
|
using ::testing::AnyNumber;
|
|
using ::testing::AtLeast;
|
|
using ::testing::ContainsRegex;
|
|
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::Ref;
|
|
using ::testing::Return;
|
|
using ::testing::ReturnNew;
|
|
using ::testing::ReturnRef;
|
|
using ::testing::SaveArg;
|
|
using ::testing::SetArgumentPointee;
|
|
using ::testing::StrEq;
|
|
using ::testing::StrictMock;
|
|
using ::testing::Test;
|
|
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;
|
|
const int kInterfaceIndex = 1234;
|
|
|
|
// Bytes representing a NL80211_CMD_NEW_WIPHY message reporting the WiFi
|
|
// capabilities of a NIC with wiphy index |kNewWiphyNlMsg_WiphyIndex| which
|
|
// supports operating bands with the frequencies specified in
|
|
// |kNewWiphyNlMsg_UniqueFrequencies|.
|
|
const uint8_t kNewWiphyNlMsg[] = {
|
|
0x68, 0x0c, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
|
0xf6, 0x31, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x02, 0x00, 0x70, 0x68, 0x79, 0x30,
|
|
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00,
|
|
0x05, 0x00, 0x3d, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x3e, 0x00,
|
|
0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff,
|
|
0x08, 0x00, 0x40, 0x00, 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x59, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x00, 0x00,
|
|
0x05, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x38, 0x00,
|
|
0xd1, 0x08, 0x00, 0x00, 0x06, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x05, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00,
|
|
0x04, 0x00, 0x8b, 0x00, 0x04, 0x00, 0x8c, 0x00, 0x18, 0x00, 0x39, 0x00,
|
|
0x01, 0xac, 0x0f, 0x00, 0x05, 0xac, 0x0f, 0x00, 0x02, 0xac, 0x0f, 0x00,
|
|
0x04, 0xac, 0x0f, 0x00, 0x06, 0xac, 0x0f, 0x00, 0x05, 0x00, 0x56, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x66, 0x00, 0x08, 0x00, 0x71, 0x00,
|
|
0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x72, 0x00, 0x03, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x69, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x6a, 0x00,
|
|
0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x20, 0x00, 0x04, 0x00, 0x01, 0x00,
|
|
0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00,
|
|
0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x08, 0x00,
|
|
0x04, 0x00, 0x09, 0x00, 0x50, 0x05, 0x16, 0x00, 0xf8, 0x01, 0x00, 0x00,
|
|
0x14, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00,
|
|
0xef, 0x11, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00,
|
|
0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, 0x01, 0x01, 0x00,
|
|
0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x6c, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0x6c, 0x07, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x71, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0x6c, 0x07, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x76, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x6c, 0x07, 0x00, 0x00,
|
|
0x14, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 0x7b, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0x6c, 0x07, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x80, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0x6c, 0x07, 0x00, 0x00, 0x14, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x85, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x6c, 0x07, 0x00, 0x00,
|
|
0x14, 0x00, 0x06, 0x00, 0x08, 0x00, 0x01, 0x00, 0x8a, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0x6c, 0x07, 0x00, 0x00, 0x14, 0x00, 0x07, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x8f, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0x6c, 0x07, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x94, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x6c, 0x07, 0x00, 0x00,
|
|
0x14, 0x00, 0x09, 0x00, 0x08, 0x00, 0x01, 0x00, 0x99, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0x6c, 0x07, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x9e, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0x6c, 0x07, 0x00, 0x00, 0x18, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0xa3, 0x09, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0x6c, 0x07, 0x00, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0xa8, 0x09, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0x6c, 0x07, 0x00, 0x00, 0x18, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0xb4, 0x09, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0xd0, 0x07, 0x00, 0x00, 0xa0, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
|
|
0x10, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x37, 0x00, 0x00, 0x00,
|
|
0x04, 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x6e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x04, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x05, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x78, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x09, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x68, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x0a, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x0b, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x1c, 0x02, 0x00, 0x00, 0x54, 0x03, 0x01, 0x00,
|
|
0x14, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00,
|
|
0xef, 0x11, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00,
|
|
0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x01, 0x00,
|
|
0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x3c, 0x14, 0x00, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x50, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
|
|
0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00,
|
|
0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x64, 0x14, 0x00, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x78, 0x14, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x8c, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00,
|
|
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00,
|
|
0x20, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00, 0xa0, 0x14, 0x00, 0x00,
|
|
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x06, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0xb4, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
|
|
0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0xc8, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00,
|
|
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00,
|
|
0x20, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0x7c, 0x15, 0x00, 0x00,
|
|
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x09, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x90, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
|
|
0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0xa4, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00,
|
|
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00,
|
|
0x20, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00, 0xb8, 0x15, 0x00, 0x00,
|
|
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x0c, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0xcc, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
|
|
0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0xe0, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00,
|
|
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00,
|
|
0x20, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x01, 0x00, 0xf4, 0x15, 0x00, 0x00,
|
|
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x0f, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x08, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
|
|
0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x1c, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00,
|
|
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00,
|
|
0x20, 0x00, 0x11, 0x00, 0x08, 0x00, 0x01, 0x00, 0x30, 0x16, 0x00, 0x00,
|
|
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x20, 0x00, 0x12, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x44, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
|
|
0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0xd0, 0x07, 0x00, 0x00, 0x14, 0x00, 0x13, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x71, 0x16, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00,
|
|
0x1c, 0x00, 0x14, 0x00, 0x08, 0x00, 0x01, 0x00, 0x85, 0x16, 0x00, 0x00,
|
|
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0xd0, 0x07, 0x00, 0x00, 0x1c, 0x00, 0x15, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x99, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x1c, 0x00, 0x16, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0xad, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
|
|
0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x07, 0x00, 0x00,
|
|
0x1c, 0x00, 0x17, 0x00, 0x08, 0x00, 0x01, 0x00, 0xc1, 0x16, 0x00, 0x00,
|
|
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0xd0, 0x07, 0x00, 0x00, 0x64, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x78, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x05, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x68, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x1c, 0x02, 0x00, 0x00, 0xd4, 0x00, 0x32, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
|
0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00,
|
|
0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x19, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x07, 0x00, 0x25, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
|
|
0x26, 0x00, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00, 0x27, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x0a, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x00,
|
|
0x2b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x37, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x0d, 0x00, 0x39, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00,
|
|
0x3b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0f, 0x00, 0x43, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x10, 0x00, 0x31, 0x00, 0x00, 0x00, 0x08, 0x00, 0x11, 0x00,
|
|
0x41, 0x00, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00, 0x42, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x13, 0x00, 0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00,
|
|
0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x00, 0x54, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x16, 0x00, 0x57, 0x00, 0x00, 0x00, 0x08, 0x00, 0x17, 0x00,
|
|
0x55, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x2d, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x19, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1a, 0x00,
|
|
0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x6f, 0x00, 0x88, 0x13, 0x00, 0x00,
|
|
0x04, 0x00, 0x6c, 0x00, 0xac, 0x03, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00,
|
|
0x84, 0x00, 0x01, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00,
|
|
0x84, 0x00, 0x02, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00,
|
|
0x84, 0x00, 0x03, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00,
|
|
0x84, 0x00, 0x04, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00,
|
|
0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x84, 0x00, 0x07, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x08, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x09, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x14, 0x01, 0x64, 0x00,
|
|
0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xd0, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
|
|
0x3c, 0x00, 0x03, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
|
|
0x3c, 0x00, 0x04, 0x00, 0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
|
|
0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x1c, 0x00, 0x07, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
|
|
0x14, 0x00, 0x08, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x09, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
|
|
0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00,
|
|
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x79, 0x00,
|
|
0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x06, 0x00, 0x50, 0x00, 0x78, 0x00,
|
|
0x4c, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x01, 0x00,
|
|
0x08, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00,
|
|
0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x08, 0x00,
|
|
0x18, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
|
|
0x0c, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x09, 0x00,
|
|
0x08, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
|
0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x8f, 0x00, 0x03, 0x00, 0x00, 0x00,
|
|
0x1e, 0x00, 0x94, 0x00, 0x42, 0x08, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
const uint32_t kNewWiphyNlMsg_WiphyIndex = 2;
|
|
const int kNewWiphyNlMsg_Nl80211AttrWiphyOffset = 4;
|
|
const uint16_t kNewWiphyNlMsg_UniqueFrequencies[] = {
|
|
2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457,
|
|
2462, 2467, 2472, 2484, 5180, 5200, 5220, 5240, 5260, 5280,
|
|
5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640,
|
|
5660, 5680, 5700, 5745, 5765, 5785, 5805, 5825};
|
|
|
|
const uint32_t kScanTriggerMsgWiphyIndex = 0;
|
|
const uint8_t kActiveScanTriggerNlMsg[] = {
|
|
0x44, 0x01, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
|
|
0x0c, 0x00, 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x08, 0x00, 0x2d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x2c, 0x00,
|
|
0x08, 0x00, 0x00, 0x00, 0x6c, 0x09, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x71, 0x09, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x76, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x03, 0x00, 0x7b, 0x09, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
|
|
0x80, 0x09, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00, 0x85, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x06, 0x00, 0x8a, 0x09, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00,
|
|
0x8f, 0x09, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x94, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x09, 0x00, 0x99, 0x09, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00,
|
|
0x9e, 0x09, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x3c, 0x14, 0x00, 0x00,
|
|
0x08, 0x00, 0x0c, 0x00, 0x50, 0x14, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00,
|
|
0x64, 0x14, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x78, 0x14, 0x00, 0x00,
|
|
0x08, 0x00, 0x0f, 0x00, 0x8c, 0x14, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00,
|
|
0xa0, 0x14, 0x00, 0x00, 0x08, 0x00, 0x11, 0x00, 0xb4, 0x14, 0x00, 0x00,
|
|
0x08, 0x00, 0x12, 0x00, 0xc8, 0x14, 0x00, 0x00, 0x08, 0x00, 0x13, 0x00,
|
|
0x7c, 0x15, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x90, 0x15, 0x00, 0x00,
|
|
0x08, 0x00, 0x15, 0x00, 0xa4, 0x15, 0x00, 0x00, 0x08, 0x00, 0x16, 0x00,
|
|
0xb8, 0x15, 0x00, 0x00, 0x08, 0x00, 0x17, 0x00, 0xcc, 0x15, 0x00, 0x00,
|
|
0x08, 0x00, 0x18, 0x00, 0x1c, 0x16, 0x00, 0x00, 0x08, 0x00, 0x19, 0x00,
|
|
0x30, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1a, 0x00, 0x44, 0x16, 0x00, 0x00,
|
|
0x08, 0x00, 0x1b, 0x00, 0x58, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1c, 0x00,
|
|
0x71, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x85, 0x16, 0x00, 0x00,
|
|
0x08, 0x00, 0x1e, 0x00, 0x99, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1f, 0x00,
|
|
0xad, 0x16, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0xc1, 0x16, 0x00, 0x00};
|
|
|
|
const uint8_t kPassiveScanTriggerNlMsg[] = {
|
|
0x40, 0x01, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
|
|
0x0c, 0x00, 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x04, 0x00, 0x2d, 0x00, 0x0c, 0x01, 0x2c, 0x00, 0x08, 0x00, 0x00, 0x00,
|
|
0x6c, 0x09, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x71, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x02, 0x00, 0x76, 0x09, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00,
|
|
0x7b, 0x09, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x80, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x05, 0x00, 0x85, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
|
|
0x8a, 0x09, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x8f, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x08, 0x00, 0x94, 0x09, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00,
|
|
0x99, 0x09, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x9e, 0x09, 0x00, 0x00,
|
|
0x08, 0x00, 0x0b, 0x00, 0x3c, 0x14, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
|
|
0x50, 0x14, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x64, 0x14, 0x00, 0x00,
|
|
0x08, 0x00, 0x0e, 0x00, 0x78, 0x14, 0x00, 0x00, 0x08, 0x00, 0x0f, 0x00,
|
|
0x8c, 0x14, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0xa0, 0x14, 0x00, 0x00,
|
|
0x08, 0x00, 0x11, 0x00, 0xb4, 0x14, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00,
|
|
0xc8, 0x14, 0x00, 0x00, 0x08, 0x00, 0x13, 0x00, 0x7c, 0x15, 0x00, 0x00,
|
|
0x08, 0x00, 0x14, 0x00, 0x90, 0x15, 0x00, 0x00, 0x08, 0x00, 0x15, 0x00,
|
|
0xa4, 0x15, 0x00, 0x00, 0x08, 0x00, 0x16, 0x00, 0xb8, 0x15, 0x00, 0x00,
|
|
0x08, 0x00, 0x17, 0x00, 0xcc, 0x15, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00,
|
|
0x1c, 0x16, 0x00, 0x00, 0x08, 0x00, 0x19, 0x00, 0x30, 0x16, 0x00, 0x00,
|
|
0x08, 0x00, 0x1a, 0x00, 0x44, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1b, 0x00,
|
|
0x58, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x71, 0x16, 0x00, 0x00,
|
|
0x08, 0x00, 0x1d, 0x00, 0x85, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x00,
|
|
0x99, 0x16, 0x00, 0x00, 0x08, 0x00, 0x1f, 0x00, 0xad, 0x16, 0x00, 0x00,
|
|
0x08, 0x00, 0x20, 0x00, 0xc1, 0x16, 0x00, 0x00};
|
|
|
|
} // namespace
|
|
|
|
class WiFiPropertyTest : public PropertyStoreTest {
|
|
public:
|
|
WiFiPropertyTest()
|
|
: metrics_(nullptr),
|
|
device_(
|
|
new WiFi(control_interface(), dispatcher(), &metrics_,
|
|
manager(), "wifi", "", kInterfaceIndex)) {
|
|
}
|
|
virtual ~WiFiPropertyTest() {}
|
|
|
|
protected:
|
|
MockMetrics metrics_;
|
|
WiFiRefPtr device_;
|
|
};
|
|
|
|
TEST_F(WiFiPropertyTest, Contains) {
|
|
EXPECT_TRUE(device_->store().Contains(kNameProperty));
|
|
EXPECT_FALSE(device_->store().Contains(""));
|
|
}
|
|
|
|
TEST_F(WiFiPropertyTest, SetProperty) {
|
|
{
|
|
Error error;
|
|
EXPECT_TRUE(device_->mutable_store()->SetAnyProperty(
|
|
kBgscanSignalThresholdProperty, PropertyStoreTest::kInt32V, &error));
|
|
}
|
|
{
|
|
Error error;
|
|
EXPECT_TRUE(device_->mutable_store()->SetAnyProperty(
|
|
kScanIntervalProperty, PropertyStoreTest::kUint16V, &error));
|
|
}
|
|
// Ensure that an attempt to write a R/O property returns InvalidArgs error.
|
|
{
|
|
Error error;
|
|
EXPECT_FALSE(device_->mutable_store()->SetAnyProperty(
|
|
kScanningProperty, PropertyStoreTest::kBoolV, &error));
|
|
ASSERT_TRUE(error.IsFailure());
|
|
EXPECT_EQ(Error::kInvalidArguments, error.type());
|
|
}
|
|
|
|
{
|
|
Error error;
|
|
EXPECT_TRUE(device_->mutable_store()->SetAnyProperty(
|
|
kBgscanMethodProperty,
|
|
brillo::Any(string(WPASupplicant::kNetworkBgscanMethodSimple)),
|
|
&error));
|
|
}
|
|
|
|
{
|
|
Error error;
|
|
EXPECT_FALSE(device_->mutable_store()->SetAnyProperty(
|
|
kBgscanMethodProperty,
|
|
brillo::Any(string("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(
|
|
kBgscanMethodProperty, &method, &unused_error));
|
|
EXPECT_EQ(WiFi::kDefaultBgscanMethod, method);
|
|
EXPECT_EQ(WPASupplicant::kNetworkBgscanMethodSimple, method);
|
|
|
|
Error error;
|
|
EXPECT_TRUE(device_->mutable_store()->SetAnyProperty(
|
|
kBgscanMethodProperty,
|
|
brillo::Any(string(WPASupplicant::kNetworkBgscanMethodLearn)),
|
|
&error));
|
|
EXPECT_EQ(WPASupplicant::kNetworkBgscanMethodLearn, device_->bgscan_method_);
|
|
EXPECT_TRUE(device_->store().GetStringProperty(
|
|
kBgscanMethodProperty, &method, &unused_error));
|
|
EXPECT_EQ(WPASupplicant::kNetworkBgscanMethodLearn, method);
|
|
|
|
EXPECT_TRUE(device_->mutable_store()->ClearProperty(
|
|
kBgscanMethodProperty, &error));
|
|
EXPECT_TRUE(device_->store().GetStringProperty(
|
|
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:
|
|
// Note: When this constructor is called (via the initialization lists in the
|
|
// constructors of WiFiMainTest and WiFiTimerTest), |dispatcher| will point to
|
|
// an uninitialized EventDispatcher. Any functions (including constructors in
|
|
// the initialization list) that use the message loop should not be called in
|
|
// this constructor, since the delayed initialization of the message loop can
|
|
// cause concurrency-related bugs. (See crbug.com/509138 for an example.)
|
|
explicit WiFiObjectTest(EventDispatcher* dispatcher)
|
|
: event_dispatcher_(dispatcher),
|
|
metrics_(nullptr),
|
|
manager_(&control_interface_, nullptr, &metrics_),
|
|
device_info_(&control_interface_, dispatcher, &metrics_, &manager_),
|
|
wifi_(new WiFi(&control_interface_, dispatcher, &metrics_, &manager_,
|
|
kDeviceName, kDeviceAddress, kInterfaceIndex)),
|
|
bss_counter_(0),
|
|
mac80211_monitor_(new StrictMock<MockMac80211Monitor>(
|
|
dispatcher, kDeviceName, WiFi::kStuckQueueLengthThreshold,
|
|
base::Closure(), &metrics_)),
|
|
supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()),
|
|
supplicant_bss_proxy_(new NiceMock<MockSupplicantBSSProxy>()),
|
|
dhcp_config_(new MockDHCPConfig(&control_interface_, kDeviceName)),
|
|
adaptor_(new DeviceMockAdaptor()),
|
|
eap_state_handler_(new NiceMock<MockSupplicantEAPStateHandler>()),
|
|
supplicant_interface_proxy_(
|
|
new NiceMock<MockSupplicantInterfaceProxy>()),
|
|
supplicant_network_proxy_(new NiceMock<MockSupplicantNetworkProxy>()) {
|
|
wifi_->mac80211_monitor_.reset(mac80211_monitor_);
|
|
wifi_->supplicant_process_proxy_.reset(supplicant_process_proxy_);
|
|
InstallMockScanSession();
|
|
ON_CALL(*supplicant_process_proxy_, CreateInterface(_, _))
|
|
.WillByDefault(DoAll(SetArgumentPointee<1>(string("/default/path")),
|
|
Return(true)));
|
|
ON_CALL(*supplicant_process_proxy_, GetInterface(_, _))
|
|
.WillByDefault(DoAll(SetArgumentPointee<1>(string("/default/path")),
|
|
Return(true)));
|
|
ON_CALL(*supplicant_interface_proxy_.get(), AddNetwork(_, _))
|
|
.WillByDefault(DoAll(SetArgumentPointee<1>(string("/default/path")),
|
|
Return(true)));
|
|
ON_CALL(*supplicant_interface_proxy_.get(), Disconnect())
|
|
.WillByDefault(Return(true));
|
|
ON_CALL(*supplicant_interface_proxy_.get(), RemoveNetwork(_))
|
|
.WillByDefault(Return(true));
|
|
ON_CALL(*supplicant_interface_proxy_.get(), Scan(_))
|
|
.WillByDefault(Return(true));
|
|
ON_CALL(*supplicant_network_proxy_.get(), SetEnabled(_))
|
|
.WillByDefault(Return(true));
|
|
|
|
EXPECT_CALL(*mac80211_monitor_, UpdateConnectedState(_))
|
|
.Times(AnyNumber());
|
|
|
|
ON_CALL(dhcp_provider_, CreateIPv4Config(_, _, _, _))
|
|
.WillByDefault(Return(dhcp_config_));
|
|
ON_CALL(*dhcp_config_.get(), RequestIP()).WillByDefault(Return(true));
|
|
ON_CALL(*manager(), IsSuspending()).WillByDefault(Return(false));
|
|
|
|
ON_CALL(control_interface_, CreateSupplicantInterfaceProxy(_, _))
|
|
.WillByDefault(ReturnAndReleasePointee(&supplicant_interface_proxy_));
|
|
ON_CALL(control_interface_, CreateSupplicantBSSProxy(_, _))
|
|
.WillByDefault(ReturnAndReleasePointee(&supplicant_bss_proxy_));
|
|
ON_CALL(control_interface_, CreateSupplicantNetworkProxy(_))
|
|
.WillByDefault(ReturnAndReleasePointee(&supplicant_network_proxy_));
|
|
Nl80211Message::SetMessageType(kNl80211FamilyId);
|
|
|
|
// Transfers ownership.
|
|
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);
|
|
static_cast<Device*>(wifi_.get())->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());
|
|
// Must be called here instead of in the constructor so that the destructor
|
|
// of SimpleAlarmTimer will not be invoked before the EventDispatcher is
|
|
// properly constructed (crbug.com/509138).
|
|
InstallMockWakeOnWiFi();
|
|
}
|
|
|
|
virtual void TearDown() {
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(_))
|
|
.WillRepeatedly(Return(nullptr));
|
|
wifi_->SelectService(nullptr);
|
|
if (supplicant_bss_proxy_.get()) {
|
|
EXPECT_CALL(*supplicant_bss_proxy_, Die());
|
|
}
|
|
EXPECT_CALL(*mac80211_monitor_, Stop());
|
|
// 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(nullptr, ResultCallback());
|
|
wifi_->set_dhcp_provider(nullptr);
|
|
// 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() {
|
|
EXPECT_CALL(*mac80211_monitor_, Stop());
|
|
wifi_->SetEnabled(false); // Stop(nullptr, ResultCallback());
|
|
}
|
|
|
|
void ResetPendingService() {
|
|
SetPendingService(nullptr);
|
|
}
|
|
|
|
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;
|
|
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,
|
|
nullptr);
|
|
wifi_->scan_session_.reset(scan_session_);
|
|
}
|
|
|
|
void InstallMockWakeOnWiFi() {
|
|
wake_on_wifi_ = new MockWakeOnWiFi(&netlink_manager_, event_dispatcher_,
|
|
&metrics_);
|
|
wifi_->wake_on_wifi_.reset(wake_on_wifi_);
|
|
}
|
|
|
|
// 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,
|
|
const char* reason) {
|
|
wifi_->SetScanState(new_state, new_method, reason);
|
|
}
|
|
|
|
void VerifyScanState(WiFi::ScanState state, WiFi::ScanMethod method) const {
|
|
EXPECT_EQ(state, wifi_->scan_state_);
|
|
EXPECT_EQ(method, wifi_->scan_method_);
|
|
}
|
|
|
|
void SetRoamThresholdMember(uint16_t threshold) {
|
|
wifi_->roam_threshold_db_ = threshold;
|
|
}
|
|
|
|
bool SetRoamThreshold(uint16_t threshold) {
|
|
return wifi_->SetRoamThreshold(threshold, nullptr);
|
|
}
|
|
|
|
uint16_t GetRoamThreshold() const {
|
|
return wifi_->GetRoamThreshold(nullptr);
|
|
}
|
|
|
|
protected:
|
|
typedef scoped_refptr<MockWiFiService> MockWiFiServiceRefPtr;
|
|
|
|
// Simulate the course of events when the last endpoint 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 = StringPrintf("ssid%d", bss_counter_);
|
|
}
|
|
*path = StringPrintf("/interface/bss%d", bss_counter_);
|
|
*bssid = 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(
|
|
&control_interface_, nullptr, 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,
|
|
kModeManaged,
|
|
security,
|
|
false);
|
|
}
|
|
MockWiFiServiceRefPtr MakeMockService(const std::string& security) {
|
|
return MakeMockServiceWithSSID(vector<uint8_t>(1, 'a'), security);
|
|
}
|
|
string MakeNewEndpointAndService(int16_t signal_strength,
|
|
uint16_t frequency,
|
|
const char* mode,
|
|
WiFiEndpointRefPtr* endpoint_ptr,
|
|
MockWiFiServiceRefPtr* service_ptr) {
|
|
string ssid;
|
|
string 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;
|
|
}
|
|
string AddEndpointToService(
|
|
WiFiServiceRefPtr service,
|
|
int16_t signal_strength,
|
|
uint16_t frequency,
|
|
const char* mode,
|
|
WiFiEndpointRefPtr* endpoint_ptr) {
|
|
string ssid(service->ssid().begin(), service->ssid().end());
|
|
string 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) {
|
|
wifi_->ConnectTo(service.get());
|
|
}
|
|
void InitiateDisconnect(WiFiServiceRefPtr service) {
|
|
wifi_->DisconnectFrom(service.get());
|
|
}
|
|
void InitiateDisconnectIfActive(WiFiServiceRefPtr service) {
|
|
wifi_->DisconnectFromIfActive(service.get());
|
|
}
|
|
MockWiFiServiceRefPtr SetupConnectingService(
|
|
const string& network_path,
|
|
WiFiEndpointRefPtr* endpoint_ptr,
|
|
string* bss_path_ptr) {
|
|
MockWiFiServiceRefPtr service;
|
|
WiFiEndpointRefPtr endpoint;
|
|
string bss_path(MakeNewEndpointAndService(
|
|
0, 0, kNetworkModeAdHoc, &endpoint, &service));
|
|
if (!network_path.empty()) {
|
|
EXPECT_CALL(*service, GetSupplicantConfigurationParameters());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), AddNetwork(_, _))
|
|
.WillOnce(DoAll(SetArgumentPointee<1>(network_path), Return(true)));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(),
|
|
SetHT40Enable(network_path, true));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), SelectNetwork(network_path));
|
|
}
|
|
EXPECT_CALL(*service, SetState(Service::kStateAssociating));
|
|
InitiateConnect(service);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
EXPECT_FALSE(GetPendingTimeout().IsCancelled());
|
|
if (endpoint_ptr) {
|
|
*endpoint_ptr = endpoint;
|
|
}
|
|
if (bss_path_ptr) {
|
|
*bss_path_ptr = bss_path;
|
|
}
|
|
return service;
|
|
}
|
|
|
|
MockWiFiServiceRefPtr SetupConnectedService(
|
|
const string& network_path,
|
|
WiFiEndpointRefPtr* endpoint_ptr,
|
|
string* bss_path_ptr) {
|
|
WiFiEndpointRefPtr endpoint;
|
|
string 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.get());
|
|
|
|
EXPECT_CALL(*service, SetState(Service::kStateConfiguring));
|
|
EXPECT_CALL(*service, ResetSuspectedCredentialFailures());
|
|
EXPECT_CALL(*dhcp_provider(), CreateIPv4Config(_, _, _, _))
|
|
.Times(AnyNumber());
|
|
EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber());
|
|
EXPECT_CALL(wifi_provider_, IncrementConnectCount(_));
|
|
ReportStateChanged(WPASupplicant::kInterfaceStateCompleted);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
EXPECT_EQ(service, GetCurrentService());
|
|
return service;
|
|
}
|
|
|
|
void FireScanTimer() {
|
|
wifi_->ScanTimerHandler();
|
|
}
|
|
void TriggerScan(WiFi::ScanMethod method) {
|
|
if (method == WiFi::kScanMethodFull) {
|
|
wifi_->Scan(Device::kFullScan, nullptr, __func__);
|
|
} else {
|
|
wifi_->Scan(Device::kProgressiveScan, nullptr, __func__);
|
|
}
|
|
}
|
|
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_;
|
|
}
|
|
const ServiceRefPtr& GetSelectedService() {
|
|
return wifi_->selected_service();
|
|
}
|
|
const string& GetSupplicantBSS() {
|
|
return wifi_->supplicant_bss_;
|
|
}
|
|
void SetSupplicantBSS(const string& bss) {
|
|
wifi_->supplicant_bss_ = bss;
|
|
}
|
|
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 static_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();
|
|
}
|
|
const string& GetSupplicantState() {
|
|
return wifi_->supplicant_state_;
|
|
}
|
|
int GetSupplicantDisconnectReason() {
|
|
return wifi_->supplicant_disconnect_reason_;
|
|
}
|
|
void ClearCachedCredentials(const WiFiService* service) {
|
|
return wifi_->ClearCachedCredentials(service);
|
|
}
|
|
void NotifyEndpointChanged(const WiFiEndpointConstRefPtr& endpoint) {
|
|
wifi_->NotifyEndpointChanged(endpoint);
|
|
}
|
|
bool RemoveNetwork(const string& network) {
|
|
return wifi_->RemoveNetwork(network);
|
|
}
|
|
KeyValueStore CreateBSSProperties(const string& ssid,
|
|
const string& bssid,
|
|
int16_t signal_strength,
|
|
uint16_t frequency,
|
|
const char* mode);
|
|
void RemoveBSS(const string& bss_path);
|
|
void ReportBSS(const string& bss_path,
|
|
const string& ssid,
|
|
const string& bssid,
|
|
int16_t signal_strength,
|
|
uint16_t frequency,
|
|
const char* mode);
|
|
void ReportIPConfigComplete() {
|
|
wifi_->OnIPConfigUpdated(dhcp_config_, true);
|
|
}
|
|
void ReportIPConfigCompleteGatewayArpReceived() {
|
|
wifi_->OnIPConfigUpdated(dhcp_config_, false);
|
|
}
|
|
|
|
// Calls the delayed version of the BSS methods.
|
|
void BSSAdded(const string& bss_path,
|
|
const KeyValueStore& properties) {
|
|
wifi_->BSSAdded(bss_path, properties);
|
|
}
|
|
void BSSRemoved(const string& bss_path) {
|
|
wifi_->BSSRemoved(bss_path);
|
|
}
|
|
|
|
void ReportIPv6ConfigComplete() {
|
|
wifi_->OnIPv6ConfigUpdated();
|
|
}
|
|
void ReportIPConfigFailure() {
|
|
wifi_->OnIPConfigFailure();
|
|
}
|
|
void ReportConnected() {
|
|
wifi_->OnConnected();
|
|
}
|
|
void ReportLinkUp() {
|
|
wifi_->LinkEvent(IFF_LOWER_UP, IFF_LOWER_UP);
|
|
}
|
|
void ScanDone(const bool& success) {
|
|
wifi_->ScanDone(success);
|
|
}
|
|
void ReportScanFailed() {
|
|
wifi_->ScanFailedTask();
|
|
}
|
|
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 ReportDisconnectReasonChanged(int reason) {
|
|
wifi_->DisconnectReasonChanged(reason);
|
|
}
|
|
void ReportWiFiDebugScopeChanged(bool enabled) {
|
|
wifi_->OnWiFiDebugScopeChanged(enabled);
|
|
}
|
|
void RequestStationInfo() {
|
|
wifi_->RequestStationInfo();
|
|
}
|
|
void ReportReceivedStationInfo(const Nl80211Message& nl80211_message) {
|
|
wifi_->OnReceivedStationInfo(nl80211_message);
|
|
}
|
|
KeyValueStore GetLinkStatistics() {
|
|
return wifi_->GetLinkStatistics(nullptr);
|
|
}
|
|
void SetPendingService(const WiFiServiceRefPtr& service) {
|
|
wifi_->SetPendingService(service);
|
|
}
|
|
void SetServiceNetworkRpcId(
|
|
const WiFiServiceRefPtr& service, const string& rpcid) {
|
|
wifi_->rpcid_by_service_[service.get()] = rpcid;
|
|
}
|
|
bool RpcIdByServiceIsEmpty() {
|
|
return wifi_->rpcid_by_service_.empty();
|
|
}
|
|
bool SetScanInterval(uint16_t interval_seconds, Error* error) {
|
|
return wifi_->SetScanInterval(interval_seconds, error);
|
|
}
|
|
uint16_t GetScanInterval() {
|
|
return wifi_->GetScanInterval(nullptr);
|
|
}
|
|
void StartWiFi(bool supplicant_present) {
|
|
EXPECT_CALL(netlink_manager_, SubscribeToEvents(
|
|
Nl80211Message::kMessageTypeString,
|
|
NetlinkManager::kEventTypeConfig));
|
|
EXPECT_CALL(netlink_manager_, SubscribeToEvents(
|
|
Nl80211Message::kMessageTypeString,
|
|
NetlinkManager::kEventTypeScan));
|
|
EXPECT_CALL(netlink_manager_, SubscribeToEvents(
|
|
Nl80211Message::kMessageTypeString,
|
|
NetlinkManager::kEventTypeRegulatory));
|
|
EXPECT_CALL(netlink_manager_, SubscribeToEvents(
|
|
Nl80211Message::kMessageTypeString,
|
|
NetlinkManager::kEventTypeMlme));
|
|
EXPECT_CALL(netlink_manager_, SendNl80211Message(
|
|
IsNl80211Command(kNl80211FamilyId, NL80211_CMD_GET_WIPHY), _, _, _));
|
|
|
|
wifi_->supplicant_present_ = supplicant_present;
|
|
wifi_->SetEnabled(true); // Start(nullptr, ResultCallback());
|
|
if (supplicant_present)
|
|
// Mimic the callback from |supplicant_process_proxy_|.
|
|
wifi_->OnSupplicantAppear();
|
|
}
|
|
void StartWiFi() {
|
|
StartWiFi(true);
|
|
}
|
|
void OnAfterResume() {
|
|
EXPECT_CALL(*wake_on_wifi_, OnAfterResume());
|
|
wifi_->OnAfterResume();
|
|
}
|
|
void OnBeforeSuspend() {
|
|
ResultCallback callback(
|
|
base::Bind(&WiFiObjectTest::SuspendCallback, base::Unretained(this)));
|
|
wifi_->OnBeforeSuspend(callback);
|
|
}
|
|
void OnDarkResume() {
|
|
ResultCallback callback(
|
|
base::Bind(&WiFiObjectTest::SuspendCallback, base::Unretained(this)));
|
|
wifi_->OnDarkResume(callback);
|
|
}
|
|
void RemoveSupplicantNetworks() {
|
|
wifi_->RemoveSupplicantNetworks();
|
|
}
|
|
void InitiateScan(Device::ScanType scan_type) {
|
|
wifi_->InitiateScan(scan_type);
|
|
}
|
|
void InitiateScanInDarkResume(const WiFi::FreqSet& freqs) {
|
|
wifi_->InitiateScanInDarkResume(freqs);
|
|
}
|
|
void TriggerPassiveScan(const WiFi::FreqSet& freqs) {
|
|
wifi_->TriggerPassiveScan(freqs);
|
|
}
|
|
void OnSupplicantAppear() {
|
|
wifi_->OnSupplicantAppear();
|
|
EXPECT_TRUE(wifi_->supplicant_present_);
|
|
}
|
|
void OnSupplicantVanish() {
|
|
wifi_->OnSupplicantVanish();
|
|
EXPECT_FALSE(wifi_->supplicant_present_);
|
|
}
|
|
bool GetSupplicantPresent() {
|
|
return wifi_->supplicant_present_;
|
|
}
|
|
bool GetIsRoamingInProgress() {
|
|
return wifi_->is_roaming_in_progress_;
|
|
}
|
|
void SetIPConfig(const IPConfigRefPtr& ipconfig) {
|
|
return wifi_->set_ipconfig(ipconfig);
|
|
}
|
|
bool SetBgscanMethod(const string& method) {
|
|
Error error;
|
|
return wifi_->mutable_store()->SetAnyProperty(kBgscanMethodProperty,
|
|
brillo::Any(method),
|
|
&error);
|
|
}
|
|
|
|
void AppendBgscan(WiFiService* service,
|
|
KeyValueStore* service_params) {
|
|
wifi_->AppendBgscan(service, service_params);
|
|
}
|
|
|
|
void ReportCertification(const KeyValueStore& properties) {
|
|
wifi_->CertificationTask(properties);
|
|
}
|
|
|
|
void ReportEAPEvent(const string& status, const string& parameter) {
|
|
wifi_->EAPEventTask(status, parameter);
|
|
}
|
|
|
|
void RestartFastScanAttempts() {
|
|
wifi_->RestartFastScanAttempts();
|
|
}
|
|
|
|
void SetFastScansRemaining(int num) {
|
|
wifi_->fast_scans_remaining_ = num;
|
|
}
|
|
|
|
void StartReconnectTimer() {
|
|
wifi_->StartReconnectTimer();
|
|
}
|
|
|
|
void StopReconnectTimer() {
|
|
wifi_->StopReconnectTimer();
|
|
}
|
|
|
|
void SetLinkMonitor(LinkMonitor* link_monitor) {
|
|
wifi_->set_link_monitor(link_monitor);
|
|
}
|
|
|
|
bool SuspectCredentials(const WiFiServiceRefPtr& service,
|
|
Service::ConnectFailure* failure) {
|
|
return wifi_->SuspectCredentials(service, failure);
|
|
}
|
|
|
|
void OnLinkMonitorFailure() {
|
|
wifi_->OnLinkMonitorFailure();
|
|
}
|
|
|
|
void OnUnreliableLink() {
|
|
wifi_->OnUnreliableLink();
|
|
}
|
|
|
|
bool SetBgscanShortInterval(const uint16_t& interval, Error* error) {
|
|
return wifi_->SetBgscanShortInterval(interval, error);
|
|
}
|
|
|
|
bool SetBgscanSignalThreshold(const int32_t& threshold, Error* error) {
|
|
return wifi_->SetBgscanSignalThreshold(threshold, error);
|
|
}
|
|
|
|
void SetTDLSManager(TDLSManager* tdls_manager) {
|
|
wifi_->tdls_manager_.reset(tdls_manager);
|
|
}
|
|
|
|
void TDLSDiscoverResponse(const string& peer_address) {
|
|
wifi_->TDLSDiscoverResponse(peer_address);
|
|
}
|
|
|
|
string PerformTDLSOperation(
|
|
const string& operation, const string& peer, Error* error) {
|
|
return wifi_->PerformTDLSOperation(operation, peer, error);
|
|
}
|
|
|
|
void TimeoutPendingConnection() {
|
|
wifi_->PendingTimeoutHandler();
|
|
}
|
|
|
|
void OnNewWiphy(const Nl80211Message& new_wiphy_message) {
|
|
wifi_->OnNewWiphy(new_wiphy_message);
|
|
}
|
|
|
|
bool IsConnectedToCurrentService() {
|
|
return wifi_->IsConnectedToCurrentService();
|
|
}
|
|
|
|
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_;
|
|
}
|
|
|
|
MockWiFiProvider* wifi_provider() {
|
|
return &wifi_provider_;
|
|
}
|
|
|
|
MockMac80211Monitor* mac80211_monitor() {
|
|
return mac80211_monitor_;
|
|
}
|
|
|
|
void ReportConnectedToServiceAfterWake() {
|
|
wifi_->ReportConnectedToServiceAfterWake();
|
|
}
|
|
|
|
void StartScanTimer() {
|
|
wifi_->StartScanTimer();
|
|
}
|
|
|
|
bool ParseWiphyIndex(const Nl80211Message& nl80211_message) {
|
|
return wifi_->ParseWiphyIndex(nl80211_message);
|
|
}
|
|
|
|
uint32_t GetWiphyIndex() { return wifi_->wiphy_index_; }
|
|
|
|
void SetWiphyIndex(uint32_t index) { wifi_->wiphy_index_ = index; }
|
|
|
|
std::set<uint16_t>* GetAllScanFrequencies() {
|
|
return &wifi_->all_scan_frequencies_;
|
|
}
|
|
|
|
void OnScanStarted(const NetlinkMessage& netlink_message) {
|
|
wifi_->OnScanStarted(netlink_message);
|
|
}
|
|
|
|
bool ScanFailedCallbackIsCancelled() {
|
|
return wifi_->scan_failed_callback_.IsCancelled();
|
|
}
|
|
|
|
void SetWiFiEnabled(bool enabled) {
|
|
wifi_->enabled_ = enabled;
|
|
}
|
|
|
|
MOCK_METHOD1(SuspendCallback, void(const Error& error));
|
|
|
|
EventDispatcher* event_dispatcher_;
|
|
MockScanSession* scan_session_; // Owned by |wifi_|.
|
|
MockWakeOnWiFi* wake_on_wifi_; // Owned by |wifi_|.
|
|
NiceMock<MockRTNLHandler> rtnl_handler_;
|
|
MockTime time_;
|
|
|
|
private:
|
|
NiceMockControl control_interface_;
|
|
MockMetrics metrics_;
|
|
MockManager manager_;
|
|
MockDeviceInfo device_info_;
|
|
WiFiRefPtr wifi_;
|
|
NiceMock<MockWiFiProvider> wifi_provider_;
|
|
int bss_counter_;
|
|
MockMac80211Monitor* mac80211_monitor_; // Owned by |wifi_|.
|
|
|
|
// protected fields interspersed between private fields, due to
|
|
// initialization order
|
|
protected:
|
|
static const char kDeviceName[];
|
|
static const char kDeviceAddress[];
|
|
static const char kNetworkModeAdHoc[];
|
|
static const char kNetworkModeInfrastructure[];
|
|
static const char kBSSName[];
|
|
static const char kSSIDName[];
|
|
static const uint16_t kRoamThreshold;
|
|
|
|
MockSupplicantProcessProxy* supplicant_process_proxy_;
|
|
unique_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.
|
|
DeviceMockAdaptor* adaptor_;
|
|
MockSupplicantEAPStateHandler* eap_state_handler_;
|
|
MockNetlinkManager netlink_manager_;
|
|
|
|
private:
|
|
unique_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
|
|
unique_ptr<MockSupplicantNetworkProxy> supplicant_network_proxy_;
|
|
};
|
|
|
|
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";
|
|
const uint16_t WiFiObjectTest::kRoamThreshold = 32; // Arbitrary value.
|
|
|
|
void WiFiObjectTest::RemoveBSS(const string& bss_path) {
|
|
wifi_->BSSRemovedTask(bss_path);
|
|
}
|
|
|
|
KeyValueStore WiFiObjectTest::CreateBSSProperties(
|
|
const string& ssid,
|
|
const string& bssid,
|
|
int16_t signal_strength,
|
|
uint16_t frequency,
|
|
const char* mode) {
|
|
KeyValueStore bss_properties;
|
|
bss_properties.SetUint8s("SSID", vector<uint8_t>(ssid.begin(), ssid.end()));
|
|
{
|
|
string bssid_nosep;
|
|
vector<uint8_t> bssid_bytes;
|
|
base::RemoveChars(bssid, ":", &bssid_nosep);
|
|
base::HexStringToBytes(bssid_nosep, &bssid_bytes);
|
|
bss_properties.SetUint8s("BSSID", bssid_bytes);
|
|
}
|
|
bss_properties.SetInt16(WPASupplicant::kBSSPropertySignal, signal_strength);
|
|
bss_properties.SetUint16(WPASupplicant::kBSSPropertyFrequency, frequency);
|
|
bss_properties.SetString(WPASupplicant::kBSSPropertyMode, mode);
|
|
|
|
return bss_properties;
|
|
}
|
|
|
|
void WiFiObjectTest::ReportBSS(const string& bss_path,
|
|
const string& ssid,
|
|
const string& bssid,
|
|
int16_t signal_strength,
|
|
uint16_t frequency,
|
|
const char* mode) {
|
|
wifi_->BSSAddedTask(
|
|
bss_path,
|
|
CreateBSSProperties(ssid, bssid, signal_strength, frequency, mode));
|
|
}
|
|
|
|
// Most of our tests involve using a real EventDispatcher object.
|
|
class WiFiMainTest : public WiFiObjectTest {
|
|
public:
|
|
WiFiMainTest() : WiFiObjectTest(&dispatcher_) {}
|
|
|
|
protected:
|
|
// A progressive scan requests one or more scans, each of which asks about a
|
|
// different batch of frequencies/channels.
|
|
enum WhichBatchOfProgressiveScan {
|
|
kFirstProgressiveScanBatch,
|
|
kOnlyFullScanBatch,
|
|
kNotFirstProgressiveScanBatch
|
|
};
|
|
void StartScan(WiFi::ScanMethod method) {
|
|
if (method == WiFi::kScanMethodFull) {
|
|
EnableFullScan();
|
|
}
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
EXPECT_CALL(*adaptor_, EmitBoolChanged(kPoweredProperty, _)).
|
|
Times(AnyNumber());
|
|
// Using kFirstProgressiveScanBatch regardless of the method since
|
|
// kFOnlyFullScanBatch does exactly the same thing.
|
|
ExpectScanStart(method, false);
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
VerifyScanState(WiFi::kScanScanning, method);
|
|
}
|
|
|
|
MockWiFiServiceRefPtr AttemptConnection(WiFi::ScanMethod method,
|
|
WiFiEndpointRefPtr* endpoint,
|
|
string* bss_path) {
|
|
WiFiEndpointRefPtr dummy_endpoint;
|
|
if (!endpoint) {
|
|
endpoint = &dummy_endpoint; // If caller doesn't care about endpoint.
|
|
}
|
|
|
|
string dummy_bss_path;
|
|
if (!bss_path) {
|
|
bss_path = &dummy_bss_path; // If caller doesn't care about bss_path.
|
|
}
|
|
|
|
ExpectScanStop();
|
|
ExpectConnecting();
|
|
MockWiFiServiceRefPtr service =
|
|
SetupConnectingService("", endpoint, bss_path);
|
|
ReportScanDoneKeepScanSession();
|
|
dispatcher_.DispatchPendingEvents();
|
|
VerifyScanState(WiFi::kScanConnecting, method);
|
|
|
|
return service;
|
|
}
|
|
|
|
void ExpectScanStart(WiFi::ScanMethod method, bool is_continued) {
|
|
if (method == WiFi::kScanMethodProgressive) {
|
|
ASSERT_FALSE(IsScanSessionNull());
|
|
EXPECT_CALL(*scan_session_, HasMoreFrequencies());
|
|
EXPECT_CALL(*scan_session_, InitiateScan());
|
|
} else {
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_));
|
|
}
|
|
if (!is_continued) {
|
|
EXPECT_CALL(*adaptor_, EmitBoolChanged(kScanningProperty,
|
|
true));
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanStarted(_));
|
|
}
|
|
}
|
|
|
|
// Scanning can stop for any reason (including transitioning to connecting).
|
|
void ExpectScanStop() {
|
|
EXPECT_CALL(*adaptor_, EmitBoolChanged(kScanningProperty, false));
|
|
}
|
|
|
|
void ExpectConnecting() {
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanFinished(_));
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectStarted(_, _));
|
|
}
|
|
|
|
void ExpectConnected() {
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectFinished(_));
|
|
ExpectScanIdle();
|
|
}
|
|
|
|
void ExpectFoundNothing() {
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanFinished(_));
|
|
EXPECT_CALL(*metrics(), ResetConnectTimer(_));
|
|
ExpectScanIdle();
|
|
}
|
|
|
|
void ExpectScanIdle() {
|
|
EXPECT_CALL(*metrics(), ResetScanTimer(_));
|
|
EXPECT_CALL(*metrics(), ResetConnectTimer(_)).RetiresOnSaturation();
|
|
}
|
|
|
|
EventDispatcherForTest dispatcher_;
|
|
};
|
|
|
|
TEST_F(WiFiMainTest, ProxiesSetUpDuringStart) {
|
|
EXPECT_EQ(nullptr, GetSupplicantInterfaceProxyFromWiFi());;
|
|
|
|
StartWiFi();
|
|
EXPECT_NE(nullptr, GetSupplicantInterfaceProxyFromWiFi());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, SupplicantPresent) {
|
|
EXPECT_FALSE(GetSupplicantPresent());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, RoamThresholdProperty) {
|
|
static const uint16_t kRoamThreshold16 = 16;
|
|
static const uint16_t kRoamThreshold32 = 32;
|
|
|
|
StartWiFi(false); // No supplicant present.
|
|
OnSupplicantAppear();
|
|
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(),
|
|
SetRoamThreshold(kRoamThreshold16));
|
|
EXPECT_TRUE(SetRoamThreshold(kRoamThreshold16));
|
|
EXPECT_EQ(GetRoamThreshold(), kRoamThreshold16);
|
|
|
|
// Try a different number
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(),
|
|
SetRoamThreshold(kRoamThreshold32));
|
|
EXPECT_TRUE(SetRoamThreshold(kRoamThreshold32));
|
|
EXPECT_EQ(GetRoamThreshold(), kRoamThreshold32);
|
|
|
|
// Do not set supplicant's roam threshold property immediately if the
|
|
// current WiFi service has its own roam threshold property set.
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
service->roam_threshold_db_set_ = true;
|
|
SetCurrentService(service);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), SetRoamThreshold(_)).Times(0);
|
|
EXPECT_TRUE(SetRoamThreshold(kRoamThreshold16));
|
|
EXPECT_EQ(kRoamThreshold16, GetRoamThreshold());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, OnSupplicantAppearStarted) {
|
|
EXPECT_EQ(nullptr, GetSupplicantInterfaceProxyFromWiFi());;
|
|
|
|
StartWiFi(false); // No supplicant present.
|
|
EXPECT_EQ(nullptr, GetSupplicantInterfaceProxyFromWiFi());;
|
|
|
|
SetRoamThresholdMember(kRoamThreshold);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveAllNetworks());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), FlushBSS(0));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), SetFastReauth(false));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), SetRoamThreshold(kRoamThreshold));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), SetScanInterval(_));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), SetDisableHighBitrates(true));
|
|
|
|
OnSupplicantAppear();
|
|
EXPECT_NE(nullptr, GetSupplicantInterfaceProxyFromWiFi());
|
|
|
|
// 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_EQ(nullptr, GetSupplicantInterfaceProxyFromWiFi());
|
|
|
|
OnSupplicantAppear();
|
|
EXPECT_EQ(nullptr, GetSupplicantInterfaceProxyFromWiFi());
|
|
|
|
// 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_EQ(nullptr, GetSupplicantInterfaceProxyFromWiFi());;
|
|
|
|
StartWiFi();
|
|
EXPECT_NE(nullptr, GetSupplicantInterfaceProxyFromWiFi());
|
|
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("", &endpoint, nullptr));
|
|
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));
|
|
unique_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_EQ(nullptr, GetCurrentService());;
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, CleanStart_FullScan) {
|
|
EnableFullScan();
|
|
EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_, _));
|
|
EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_, _))
|
|
.Times(AnyNumber())
|
|
.WillRepeatedly(Return(false));
|
|
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(Return(false));
|
|
EXPECT_TRUE(GetScanTimer().IsCancelled());
|
|
StartWiFi();
|
|
EXPECT_CALL(*scan_session_, InitiateScan());
|
|
dispatcher_.DispatchPendingEvents();
|
|
EXPECT_FALSE(GetScanTimer().IsCancelled());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ClearCachedCredentials) {
|
|
StartWiFi();
|
|
string network = "/test/path";
|
|
WiFiServiceRefPtr service(SetupConnectedService(network, nullptr, nullptr));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(network));
|
|
ClearCachedCredentials(service.get());
|
|
}
|
|
|
|
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) {
|
|
string network = "/test/path";
|
|
StartWiFi();
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(network))
|
|
.WillOnce(Return(true));
|
|
EXPECT_TRUE(RemoveNetwork(network));
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, UseArpGateway) {
|
|
StartWiFi();
|
|
|
|
// With no selected service.
|
|
EXPECT_TRUE(wifi()->ShouldUseArpGateway());
|
|
EXPECT_CALL(dhcp_provider_, CreateIPv4Config(kDeviceName, _, true, _))
|
|
.WillOnce(Return(dhcp_config_));
|
|
const_cast<WiFi*>(wifi().get())->AcquireIPConfig();
|
|
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
InitiateConnect(service);
|
|
|
|
// Selected service that does not have a static IP address.
|
|
EXPECT_CALL(*service, HasStaticIPAddress()).WillRepeatedly(Return(false));
|
|
EXPECT_TRUE(wifi()->ShouldUseArpGateway());
|
|
EXPECT_CALL(dhcp_provider_, CreateIPv4Config(kDeviceName, _, true, _))
|
|
.WillOnce(Return(dhcp_config_));
|
|
const_cast<WiFi*>(wifi().get())->AcquireIPConfig();
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
// Selected service that has a static IP address.
|
|
EXPECT_CALL(*service, HasStaticIPAddress()).WillRepeatedly(Return(true));
|
|
EXPECT_FALSE(wifi()->ShouldUseArpGateway());
|
|
EXPECT_CALL(dhcp_provider_, CreateIPv4Config(kDeviceName, _, false, _))
|
|
.WillOnce(Return(dhcp_config_));
|
|
const_cast<WiFi*>(wifi().get())->AcquireIPConfig();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, RemoveNetworkFailed) {
|
|
string network = "/test/path";
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(network))
|
|
.WillRepeatedly(Return(false));
|
|
StartWiFi();
|
|
EXPECT_FALSE(RemoveNetwork(network));
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, Restart_FullScan) {
|
|
EnableFullScan();
|
|
EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_, _))
|
|
.Times(AnyNumber())
|
|
.WillRepeatedly(Return(false));
|
|
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(Return(false));
|
|
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) {
|
|
// Setup 'connecting' state.
|
|
StartScan(WiFi::kScanMethodFull);
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
|
|
ExpectScanStop();
|
|
ExpectConnecting();
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
InitiateConnect(service);
|
|
VerifyScanState(WiFi::kScanConnecting, WiFi::kScanMethodFull);
|
|
|
|
// If we're connecting, we ignore scan requests and stay on channel.
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0);
|
|
TriggerScan(WiFi::kScanMethodFull);
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
// Terminate the scan.
|
|
ExpectFoundNothing();
|
|
TimeoutPendingConnection();
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
|
|
// Start a fresh scan.
|
|
ExpectScanStart(WiFi::kScanMethodFull, false);
|
|
TriggerScan(WiFi::kScanMethodFull);
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
// Similarly, ignore scans when our connected service is reconnecting.
|
|
ExpectScanStop();
|
|
ExpectScanIdle();
|
|
SetPendingService(nullptr);
|
|
SetCurrentService(service);
|
|
EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(true));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0);
|
|
TriggerScan(WiFi::kScanMethodFull);
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
// But otherwise we'll honor the request.
|
|
EXPECT_CALL(*service, IsConnecting()).Times(AtLeast(2)).
|
|
WillRepeatedly(Return(false));
|
|
ExpectScanStart(WiFi::kScanMethodFull, false);
|
|
TriggerScan(WiFi::kScanMethodFull);
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
// Silence messages from the destructor.
|
|
ExpectScanStop();
|
|
ExpectScanIdle();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, NoScansWhileConnecting) {
|
|
// Setup 'connecting' state.
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
ExpectScanStop();
|
|
ExpectConnecting();
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
InitiateConnect(service);
|
|
VerifyScanState(WiFi::kScanConnecting, WiFi::kScanMethodProgressive);
|
|
|
|
// If we're connecting, we ignore scan requests and stay on channel.
|
|
EXPECT_CALL(*scan_session_, InitiateScan()).Times(0);
|
|
TriggerScan(WiFi::kScanMethodProgressive);
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
Mock::VerifyAndClearExpectations(scan_session_);
|
|
|
|
// Terminate the scan.
|
|
ExpectFoundNothing();
|
|
TimeoutPendingConnection();
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
|
|
// Start a fresh scan.
|
|
InstallMockScanSession();
|
|
ExpectScanStart(WiFi::kScanMethodProgressive, false);
|
|
TriggerScan(WiFi::kScanMethodProgressive);
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
Mock::VerifyAndClearExpectations(scan_session_);
|
|
|
|
// Similarly, ignore scans when our connected service is reconnecting.
|
|
ExpectScanStop();
|
|
ExpectScanIdle();
|
|
SetPendingService(nullptr);
|
|
SetCurrentService(service);
|
|
EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(true));
|
|
InstallMockScanSession();
|
|
EXPECT_CALL(*scan_session_, InitiateScan()).Times(0);
|
|
TriggerScan(WiFi::kScanMethodProgressive);
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
Mock::VerifyAndClearExpectations(scan_session_);
|
|
|
|
// Unlike Full scan, Progressive scan will reject attempts to scan while
|
|
// we're connected.
|
|
EXPECT_CALL(*service, IsConnecting()).WillOnce(Return(false));
|
|
EXPECT_CALL(*scan_session_, InitiateScan()).Times(0);
|
|
TriggerScan(WiFi::kScanMethodProgressive);
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
Mock::VerifyAndClearExpectations(scan_session_);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ResetScanStateWhenScanFailed) {
|
|
StartScan(WiFi::kScanMethodFull);
|
|
ExpectScanStop();
|
|
VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodFull);
|
|
ReportScanFailed();
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
}
|
|
|
|
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_NE(nullptr, scan_session_);;
|
|
InstallMockScanSession();
|
|
EXPECT_CALL(*scan_session_, InitiateScan());
|
|
dispatcher_.DispatchPendingEvents();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ResumeDoesNotScanIfConnected) {
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
ReportScanDone();
|
|
CancelScanTimer();
|
|
EXPECT_TRUE(GetScanTimer().IsCancelled());
|
|
ASSERT_TRUE(wifi()->IsIdle());
|
|
dispatcher_.DispatchPendingEvents();
|
|
OnAfterResume();
|
|
EXPECT_FALSE(GetScanTimer().IsCancelled());
|
|
InstallMockScanSession();
|
|
SetCurrentService(MakeMockService(kSecurityNone));
|
|
EXPECT_CALL(*scan_session_, InitiateScan()).Times(0);
|
|
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("", nullptr, nullptr));
|
|
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("", nullptr, nullptr));
|
|
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_TRUE(IsScanSessionNull());
|
|
OnAfterResume();
|
|
dispatcher_.DispatchPendingEvents();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ResumeWithCurrentService) {
|
|
StartWiFi();
|
|
SetupConnectedService("", nullptr, nullptr);
|
|
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), SetHT40Enable(_, true)).Times(1);
|
|
OnAfterResume();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
}
|
|
|
|
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_t 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);
|
|
manager()->set_suppress_autoconnect(true);
|
|
ReportScanDone();
|
|
EXPECT_FALSE(manager()->suppress_autoconnect());
|
|
Mock::VerifyAndClearExpectations(wifi_provider());
|
|
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointAdded(_)).Times(0);
|
|
|
|
// BSSes with SSIDs that start with nullptr 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;
|
|
string bss_path;
|
|
WiFiServiceRefPtr service(
|
|
SetupConnectedService("", &endpoint, &bss_path));
|
|
unique_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;
|
|
string bss_path;
|
|
WiFiServiceRefPtr service(
|
|
SetupConnectedService("", &endpoint, &bss_path));
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint)))
|
|
.WillOnce(Return(nullptr));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()).Times(0);
|
|
RemoveBSS(bss_path);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ReconnectPreservesDBusPath) {
|
|
StartWiFi();
|
|
string kPath = "/test/path";
|
|
MockWiFiServiceRefPtr service(SetupConnectedService(kPath, nullptr, nullptr));
|
|
|
|
// 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, and should not request new configuration parameters.
|
|
EXPECT_CALL(*service, GetSupplicantConfigurationParameters()).Times(0);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), AddNetwork(_, _)).Times(0);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), SelectNetwork(kPath));
|
|
InitiateConnect(service);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectPendingService) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service(
|
|
SetupConnectingService("", nullptr, nullptr));
|
|
EXPECT_TRUE(GetPendingService() == service.get());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect());
|
|
EXPECT_CALL(*service, SetFailure(_)).Times(0);
|
|
EXPECT_CALL(*service, SetState(Service::kStateIdle)).Times(AtLeast(1));
|
|
service->set_expecting_disconnect(true);
|
|
InitiateDisconnect(service);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
EXPECT_EQ(nullptr, GetPendingService());;
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectPendingServiceWithFailure) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service(
|
|
SetupConnectingService("", nullptr, nullptr));
|
|
EXPECT_TRUE(GetPendingService() == service.get());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect());
|
|
EXPECT_CALL(*service, SetFailure(Service::kFailureOutOfRange));
|
|
EXPECT_CALL(*service, SetState(Service::kStateIdle)).Times(AtLeast(1));
|
|
InitiateDisconnect(service);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
EXPECT_EQ(nullptr, GetPendingService());;
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectPendingServiceWithCurrent) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service0(
|
|
SetupConnectedService("", nullptr, nullptr));
|
|
EXPECT_EQ(service0, GetCurrentService());
|
|
EXPECT_EQ(nullptr, 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", nullptr, nullptr));
|
|
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(nullptr, GetPendingService().get());
|
|
EXPECT_TRUE(GetPendingTimeout().IsCancelled());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectCurrentService) {
|
|
StartWiFi();
|
|
string kPath("/fake/path");
|
|
MockWiFiServiceRefPtr service(SetupConnectedService(kPath, nullptr, nullptr));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect());
|
|
service->set_expecting_disconnect(true);
|
|
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.
|
|
unique_ptr<MockSupplicantNetworkProxy> network_proxy(
|
|
new MockSupplicantNetworkProxy());
|
|
EXPECT_CALL(*control_interface(),
|
|
CreateSupplicantNetworkProxy(kPath))
|
|
.WillOnce(ReturnAndReleasePointee(&network_proxy));
|
|
EXPECT_CALL(*network_proxy, SetEnabled(false)).WillOnce(Return(true));
|
|
EXPECT_CALL(*eap_state_handler_, Reset());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(kPath)).Times(0);
|
|
EXPECT_CALL(*service, SetFailure(_)).Times(0);
|
|
EXPECT_CALL(*service, SetState(Service::kStateIdle)).Times(AtLeast(1));
|
|
ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull);
|
|
EXPECT_EQ(nullptr, GetCurrentService().get());
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectCurrentServiceWithFailure) {
|
|
StartWiFi();
|
|
string kPath("/fake/path");
|
|
MockWiFiServiceRefPtr service(SetupConnectedService(kPath, nullptr, nullptr));
|
|
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.
|
|
unique_ptr<MockSupplicantNetworkProxy> network_proxy(
|
|
new MockSupplicantNetworkProxy());
|
|
EXPECT_CALL(*control_interface(),
|
|
CreateSupplicantNetworkProxy(kPath))
|
|
.WillOnce(ReturnAndReleasePointee(&network_proxy));
|
|
EXPECT_CALL(*network_proxy, SetEnabled(false)).WillOnce(Return(true));
|
|
EXPECT_CALL(*eap_state_handler_, Reset());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(kPath)).Times(0);
|
|
EXPECT_CALL(*service, SetFailure(Service::kFailureOutOfRange));
|
|
EXPECT_CALL(*service, SetState(Service::kStateIdle)).Times(AtLeast(1));
|
|
ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull);
|
|
EXPECT_EQ(nullptr, GetCurrentService().get());
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectCurrentServiceWithErrors) {
|
|
StartWiFi();
|
|
string kPath("/fake/path");
|
|
WiFiServiceRefPtr service(SetupConnectedService(kPath, nullptr, nullptr));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect())
|
|
.WillOnce(Return(false));
|
|
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(nullptr, GetCurrentService().get());
|
|
EXPECT_EQ(nullptr, GetSelectedService().get());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectCurrentServiceWithPending) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service0(SetupConnectedService("",
|
|
nullptr, nullptr));
|
|
MockWiFiServiceRefPtr service1(SetupConnectingService("",
|
|
nullptr, nullptr));
|
|
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());
|
|
|
|
EXPECT_CALL(*service0, SetState(Service::kStateIdle)).Times(AtLeast(1));
|
|
EXPECT_CALL(*service0, SetFailure(_)).Times(0);
|
|
ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectCurrentServiceWhileRoaming) {
|
|
StartWiFi();
|
|
string kPath("/fake/path");
|
|
WiFiServiceRefPtr service(SetupConnectedService(kPath, nullptr, nullptr));
|
|
|
|
// As it roams to another AP, supplicant signals that it is in
|
|
// the authenticating state.
|
|
ReportStateChanged(WPASupplicant::kInterfaceStateAuthenticating);
|
|
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(kPath));
|
|
InitiateDisconnect(service);
|
|
|
|
// Because the interface was not connected, we should have immediately
|
|
// forced ourselves into a disconnected state.
|
|
EXPECT_EQ(nullptr, GetCurrentService().get());
|
|
EXPECT_EQ(nullptr, GetSelectedService().get());
|
|
|
|
// Check calls before TearDown/dtor.
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectWithWiFiServiceConnected) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service0(SetupConnectedService("",
|
|
nullptr, nullptr));
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(2);
|
|
EXPECT_CALL(log, Log(_, _, ContainsRegex("DisconnectFromIfActive.*service")))
|
|
.Times(1);
|
|
EXPECT_CALL(log,
|
|
Log(_, _, ContainsRegex("DisconnectFrom[^a-zA-Z].*service")))
|
|
.Times(1);
|
|
EXPECT_CALL(*service0, IsActive(_)).Times(0);
|
|
InitiateDisconnectIfActive(service0);
|
|
|
|
Mock::VerifyAndClearExpectations(&log);
|
|
Mock::VerifyAndClearExpectations(service0.get());
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectWithWiFiServiceIdle) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service0(SetupConnectedService("",
|
|
nullptr, nullptr));
|
|
InitiateDisconnectIfActive(service0);
|
|
MockWiFiServiceRefPtr service1(SetupConnectedService("",
|
|
nullptr, nullptr));
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(2);
|
|
EXPECT_CALL(log, Log(_, _, ContainsRegex("DisconnectFromIfActive.*service")))
|
|
.Times(1);
|
|
EXPECT_CALL(*service0, IsActive(_)).WillOnce(Return(false));
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("is not active, no need"))).Times(1);
|
|
EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
|
|
ContainsRegex("In .*DisconnectFrom\\(.*\\):")))
|
|
.Times(0);
|
|
InitiateDisconnectIfActive(service0);
|
|
|
|
Mock::VerifyAndClearExpectations(&log);
|
|
Mock::VerifyAndClearExpectations(service0.get());
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectWithWiFiServiceConnectedInError) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service0(SetupConnectedService("",
|
|
nullptr, nullptr));
|
|
SetCurrentService(nullptr);
|
|
ResetPendingService();
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(2);
|
|
EXPECT_CALL(log, Log(_, _, ContainsRegex("DisconnectFromIfActive.*service")))
|
|
.Times(1);
|
|
EXPECT_CALL(*service0, IsActive(_)).WillOnce(Return(true));
|
|
EXPECT_CALL(log,
|
|
Log(_, _, ContainsRegex("DisconnectFrom[^a-zA-Z].*service")))
|
|
.Times(1);
|
|
EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
|
|
ContainsRegex("In .*DisconnectFrom\\(.*\\):"))).Times(1);
|
|
InitiateDisconnectIfActive(service0);
|
|
|
|
Mock::VerifyAndClearExpectations(&log);
|
|
Mock::VerifyAndClearExpectations(service0.get());
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, TimeoutPendingServiceWithEndpoints) {
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
const base::CancelableClosure& pending_timeout = GetPendingTimeout();
|
|
EXPECT_TRUE(pending_timeout.IsCancelled());
|
|
MockWiFiServiceRefPtr service = AttemptConnection(
|
|
WiFi::kScanMethodProgressive, nullptr, nullptr);
|
|
|
|
// Timeout the connection attempt.
|
|
EXPECT_FALSE(pending_timeout.IsCancelled());
|
|
EXPECT_EQ(service, GetPendingService());
|
|
// Simulate a service with a wifi_ reference calling DisconnectFrom().
|
|
EXPECT_CALL(*service,
|
|
DisconnectWithFailure(Service::kFailureOutOfRange, _,
|
|
HasSubstr("PendingTimeoutHandler")))
|
|
.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(1);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()).Times(0);
|
|
|
|
// Innocuous redundant call to NotifyDeviceScanFinished.
|
|
ExpectFoundNothing();
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectFinished(_)).Times(0);
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(10);
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log, Log(_, _,
|
|
HasSubstr("-> PROGRESSIVE_FINISHED_NOCONNECTION")));
|
|
pending_timeout.callback().Run();
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
// Service state should be idle, so it is connectable again.
|
|
EXPECT_EQ(Service::kStateIdle, service->state());
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
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("", nullptr, nullptr));
|
|
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,
|
|
_,
|
|
HasSubstr("PendingTimeoutHandler")));
|
|
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(nullptr, GetPendingService().get());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectInvalidService) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service;
|
|
MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, nullptr, &service);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect()).Times(0);
|
|
InitiateDisconnect(service);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectCurrentServiceFailure) {
|
|
StartWiFi();
|
|
string kPath("/fake/path");
|
|
WiFiServiceRefPtr service(SetupConnectedService(kPath, nullptr, nullptr));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect())
|
|
.WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(kPath));
|
|
InitiateDisconnect(service);
|
|
EXPECT_EQ(nullptr, GetCurrentService().get());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, Stop) {
|
|
StartWiFi();
|
|
WiFiEndpointRefPtr endpoint0;
|
|
string kPath("/fake/path");
|
|
WiFiServiceRefPtr service0(SetupConnectedService(kPath, &endpoint0, nullptr));
|
|
WiFiEndpointRefPtr endpoint1;
|
|
MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, &endpoint1, nullptr);
|
|
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint0)))
|
|
.WillOnce(Return(nullptr));
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint1)))
|
|
.WillOnce(Return(nullptr));
|
|
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("", &endpoint, nullptr));
|
|
unique_ptr<EndpointRemovalHandler> handler(
|
|
MakeEndpointRemovalHandler(service));
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(endpoint)))
|
|
.WillOnce(Invoke(handler.get(),
|
|
&EndpointRemovalHandler::OnEndpointRemoved));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect());
|
|
StopWiFi();
|
|
EXPECT_EQ(nullptr, GetCurrentService());;
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ReconnectTimer) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service(
|
|
SetupConnectedService("", nullptr, nullptr));
|
|
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, "") {
|
|
if (!arg.ContainsByteArrays(WPASupplicant::kPropertyScanSSIDs)) {
|
|
return false;
|
|
}
|
|
|
|
ByteArrays ssids = arg.GetByteArrays(WPASupplicant::kPropertyScanSSIDs);
|
|
// 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, "") {
|
|
return !arg.ContainsByteArrays(WPASupplicant::kPropertyScanSSIDs);
|
|
}
|
|
|
|
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(*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(*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, ScanRejected) {
|
|
StartWiFi();
|
|
ReportScanDone();
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_))
|
|
.WillOnce(Return(false));
|
|
TriggerScan(WiFi::kScanMethodFull);
|
|
dispatcher_.DispatchPendingEvents();
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
}
|
|
|
|
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).
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
EXPECT_CALL(*manager(), OnDeviceGeolocationInfoUpdated(_)).Times(0);
|
|
ReportScanDoneKeepScanSession();
|
|
|
|
// Do the second scan (connects afterwards).
|
|
ExpectScanStart(WiFi::kScanMethodProgressive, true);
|
|
dispatcher_.DispatchPendingEvents();
|
|
VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive);
|
|
ReportScanDoneKeepScanSession();
|
|
|
|
// Connect after second scan.
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanFinished(_));
|
|
EXPECT_CALL(*scan_session_, InitiateScan()).Times(0);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0);
|
|
EXPECT_CALL(*adaptor_, EmitBoolChanged(kScanningProperty, false));
|
|
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);
|
|
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);
|
|
|
|
// This test never connects
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectStarted(_, _)).Times(0);
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectFinished(_)).Times(0);
|
|
|
|
// Do the first scan (finds nothing).
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
ReportScanDoneKeepScanSession();
|
|
|
|
// Do the second scan (finds nothing).
|
|
ExpectScanStart(WiFi::kScanMethodProgressive, true);
|
|
EXPECT_CALL(*manager(), OnDeviceGeolocationInfoUpdated(_)).Times(0);
|
|
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).
|
|
ExpectScanStop();
|
|
ExpectFoundNothing();
|
|
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(); // Posts |ProgressiveScanTask|.
|
|
|
|
EXPECT_CALL(netlink_manager_, SendNl80211Message(
|
|
IsNl80211Command(kNl80211FamilyId, NL80211_CMD_TRIGGER_SCAN), _, _, _));
|
|
dispatcher_.DispatchPendingEvents(); // Executes |ProgressiveScanTask|.
|
|
|
|
// Calls |WiFi::OnFailedProgressiveScan| which calls |ScanTask|
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(1);
|
|
NewScanResultsMessage not_supposed_to_get_this_message;
|
|
OnTriggerScanResponse(not_supposed_to_get_this_message);
|
|
VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressiveErrorToFull);
|
|
|
|
EXPECT_TRUE(IsScanSessionNull());
|
|
|
|
// Post and execute |UpdateScanStateAfterScanDone|.
|
|
ReportScanDoneKeepScanSession();
|
|
dispatcher_.DispatchPendingEvents();
|
|
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(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(), CreateIPv4Config(_, _, _, _))
|
|
.Times(AnyNumber());
|
|
EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber());
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
EXPECT_CALL(*service, SetState(Service::kStateAssociating));
|
|
EXPECT_CALL(*service, SetState(Service::kStateConfiguring));
|
|
EXPECT_CALL(*service, ResetSuspectedCredentialFailures());
|
|
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.get());
|
|
EXPECT_CALL(*service, SetState(_)).Times(AnyNumber());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ConnectToServiceWithoutRecentIssues) {
|
|
MockSupplicantProcessProxy* process_proxy = supplicant_process_proxy_;
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
MockWiFiServiceRefPtr service = MakeMockService(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_;
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
EXPECT_CALL(*process_proxy, GetDebugLevel(_))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(string(WPASupplicant::kDebugLevelInfo)),
|
|
Return(true)));
|
|
EXPECT_CALL(*process_proxy, SetDebugLevel(WPASupplicant::kDebugLevelDebug))
|
|
.Times(1);
|
|
EXPECT_CALL(*service.get(), HasRecentConnectionIssues())
|
|
.WillOnce(Return(true));
|
|
InitiateConnect(service);
|
|
Mock::VerifyAndClearExpectations(process_proxy);
|
|
|
|
SetPendingService(nullptr);
|
|
SetCurrentService(service);
|
|
|
|
// When we disconnect from the troubled service, we should reduce the
|
|
// level of supplicant debugging.
|
|
EXPECT_CALL(*process_proxy, GetDebugLevel(_))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(string(WPASupplicant::kDebugLevelDebug)),
|
|
Return(true)));
|
|
EXPECT_CALL(*process_proxy, SetDebugLevel(WPASupplicant::kDebugLevelInfo))
|
|
.Times(1);
|
|
ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, CurrentBSSChangeConnectedToDisconnected) {
|
|
StartWiFi();
|
|
WiFiEndpointRefPtr endpoint;
|
|
MockWiFiServiceRefPtr service =
|
|
SetupConnectedService("", &endpoint, nullptr);
|
|
|
|
EXPECT_CALL(*service, SetState(Service::kStateIdle)).Times(AtLeast(1));
|
|
ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull);
|
|
EXPECT_EQ(nullptr, GetCurrentService().get());
|
|
EXPECT_EQ(nullptr, GetPendingService().get());
|
|
EXPECT_FALSE(GetIsRoamingInProgress());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, CurrentBSSChangeConnectedToConnectedNewService) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service0 =
|
|
SetupConnectedService("", nullptr, nullptr);
|
|
MockWiFiServiceRefPtr service1;
|
|
string bss_path1(MakeNewEndpointAndService(
|
|
0, 0, kNetworkModeAdHoc, nullptr, &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));
|
|
EXPECT_CALL(*service1, ResetSuspectedCredentialFailures());
|
|
EXPECT_CALL(*wifi_provider(), IncrementConnectCount(_));
|
|
ReportStateChanged(WPASupplicant::kInterfaceStateCompleted);
|
|
EXPECT_EQ(service1.get(), GetCurrentService().get());
|
|
EXPECT_FALSE(GetIsRoamingInProgress());
|
|
Mock::VerifyAndClearExpectations(service0.get());
|
|
Mock::VerifyAndClearExpectations(service1.get());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint) {
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive);
|
|
|
|
MockWiFiServiceRefPtr service =
|
|
SetupConnectedService("", nullptr, nullptr);
|
|
WiFiEndpointRefPtr endpoint;
|
|
string bss_path =
|
|
AddEndpointToService(service, 0, 0, kNetworkModeAdHoc, &endpoint);
|
|
EXPECT_CALL(*service, NotifyCurrentEndpoint(EndpointMatch(endpoint)));
|
|
ReportCurrentBSSChanged(bss_path);
|
|
EXPECT_TRUE(GetIsRoamingInProgress());
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
|
|
// If we report a "completed" state change on a connected service after
|
|
// wpa_supplicant has roamed, we should renew our IPConfig.
|
|
scoped_refptr<MockIPConfig> ipconfig(
|
|
new MockIPConfig(control_interface(), kDeviceName));
|
|
SetIPConfig(ipconfig);
|
|
EXPECT_CALL(*service, IsConnected()).WillOnce(Return(true));
|
|
EXPECT_CALL(*ipconfig, RenewIP());
|
|
ReportStateChanged(WPASupplicant::kInterfaceStateCompleted);
|
|
Mock::VerifyAndClearExpectations(ipconfig.get());
|
|
EXPECT_FALSE(GetIsRoamingInProgress());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectReasonUpdated) {
|
|
ScopedMockLog log;
|
|
int test_reason = 4;
|
|
int test_reason_second = 0;
|
|
EXPECT_CALL(*adaptor_, EmitBoolChanged(kPoweredProperty, _))
|
|
.Times(AnyNumber());
|
|
EXPECT_EQ(GetSupplicantDisconnectReason(), WiFi::kDefaultDisconnectReason);
|
|
EXPECT_CALL(log,
|
|
Log(logging::LOG_INFO, _, EndsWith(" DisconnectReason to 4")));
|
|
ReportDisconnectReasonChanged(test_reason);
|
|
EXPECT_EQ(GetSupplicantDisconnectReason(), test_reason);
|
|
EXPECT_CALL(log,
|
|
Log(logging::LOG_INFO, _, EndsWith("Reason to 0 (was 4)")));
|
|
ReportDisconnectReasonChanged(test_reason_second);
|
|
EXPECT_EQ(GetSupplicantDisconnectReason(), test_reason_second);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, DisconnectReasonCleared) {
|
|
int test_reason = 4;
|
|
// Clearing the value for supplicant_disconnect_reason_ is done prior to any
|
|
// early exits in the WiFi::StateChanged method. This allows the value to be
|
|
// checked without a mock pending or current service.
|
|
ReportDisconnectReasonChanged(test_reason);
|
|
EXPECT_EQ(wifi().get()->supplicant_disconnect_reason_, test_reason);
|
|
ReportStateChanged(WPASupplicant::kInterfaceStateDisconnected);
|
|
ReportStateChanged(WPASupplicant::kInterfaceStateAssociated);
|
|
EXPECT_EQ(wifi().get()->supplicant_disconnect_reason_,
|
|
WiFi::kDefaultDisconnectReason);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, NewConnectPreemptsPending) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service0(
|
|
SetupConnectingService("", nullptr, nullptr));
|
|
EXPECT_EQ(service0.get(), GetPendingService().get());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect());
|
|
MockWiFiServiceRefPtr service1(
|
|
SetupConnectingService("", nullptr, nullptr));
|
|
EXPECT_EQ(service1.get(), GetPendingService().get());
|
|
EXPECT_EQ(nullptr, GetCurrentService().get());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ConnectedToUnintendedPreemptsPending) {
|
|
StartWiFi();
|
|
string bss_path;
|
|
// Connecting two different services back-to-back.
|
|
MockWiFiServiceRefPtr unintended_service(
|
|
SetupConnectingService("", nullptr, &bss_path));
|
|
MockWiFiServiceRefPtr intended_service(
|
|
SetupConnectingService("", nullptr, nullptr));
|
|
|
|
// Verify the pending service.
|
|
EXPECT_EQ(intended_service.get(), GetPendingService().get());
|
|
|
|
// Connected to the unintended service (service0).
|
|
ReportCurrentBSSChanged(bss_path);
|
|
|
|
// Verify the pending service is disconnected, and the service state is back
|
|
// to idle, so it is connectable again.
|
|
EXPECT_EQ(nullptr, GetPendingService().get());
|
|
EXPECT_EQ(nullptr, GetCurrentService().get());
|
|
EXPECT_EQ(Service::kStateIdle, intended_service->state());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, IsIdle) {
|
|
StartWiFi();
|
|
EXPECT_TRUE(wifi()->IsIdle());
|
|
MockWiFiServiceRefPtr service(
|
|
SetupConnectingService("", nullptr, nullptr));
|
|
EXPECT_FALSE(wifi()->IsIdle());
|
|
}
|
|
|
|
MATCHER_P(WiFiAddedArgs, bgscan, "") {
|
|
return arg.ContainsUint(WPASupplicant::kNetworkPropertyScanSSID) &&
|
|
arg.ContainsUint(WPASupplicant::kNetworkPropertyDisableVHT) &&
|
|
arg.ContainsString(WPASupplicant::kNetworkPropertyBgscan) == bgscan;
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, AddNetworkArgs) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service;
|
|
MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, nullptr, &service);
|
|
EXPECT_CALL(*service, GetSupplicantConfigurationParameters());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(),
|
|
AddNetwork(WiFiAddedArgs(true), _));
|
|
EXPECT_TRUE(SetBgscanMethod(WPASupplicant::kNetworkBgscanMethodSimple));
|
|
InitiateConnect(service);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, AddNetworkArgsNoBgscan) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service;
|
|
MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, nullptr, &service);
|
|
EXPECT_CALL(*service, GetSupplicantConfigurationParameters());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(),
|
|
AddNetwork(WiFiAddedArgs(false), _));
|
|
InitiateConnect(service);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, AppendBgscan) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
{
|
|
// 1 endpoint, default bgscan method -- background scan disabled.
|
|
KeyValueStore params;
|
|
EXPECT_CALL(*service, GetEndpointCount()).WillOnce(Return(1));
|
|
AppendBgscan(service.get(), ¶ms);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
EXPECT_FALSE(params.ContainsString(WPASupplicant::kNetworkPropertyBgscan));
|
|
}
|
|
{
|
|
// 2 endpoints, default bgscan method -- background scan frequency reduced.
|
|
KeyValueStore params;
|
|
EXPECT_CALL(*service, GetEndpointCount()).WillOnce(Return(2));
|
|
AppendBgscan(service.get(), ¶ms);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
string config_string;
|
|
EXPECT_TRUE(params.ContainsString(WPASupplicant::kNetworkPropertyBgscan));
|
|
config_string = params.GetString(WPASupplicant::kNetworkPropertyBgscan);
|
|
vector<string> elements = base::SplitString(
|
|
config_string, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
|
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));
|
|
KeyValueStore params;
|
|
EXPECT_CALL(*service, GetEndpointCount()).Times(0);
|
|
AppendBgscan(service.get(), ¶ms);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
EXPECT_TRUE(params.ContainsString(WPASupplicant::kNetworkPropertyBgscan));
|
|
string config_string =
|
|
params.GetString(WPASupplicant::kNetworkPropertyBgscan);
|
|
vector<string> elements = base::SplitString(
|
|
config_string, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
|
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));
|
|
KeyValueStore params;
|
|
EXPECT_CALL(*service, GetEndpointCount()).Times(0);
|
|
AppendBgscan(service.get(), ¶ms);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
string config_string;
|
|
EXPECT_FALSE(params.ContainsString(WPASupplicant::kNetworkPropertyBgscan));
|
|
}
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, StateAndIPIgnoreLinkEvent) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service(
|
|
SetupConnectingService("", nullptr, nullptr));
|
|
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.get());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, SupplicantCompletedAlreadyConnected) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service(
|
|
SetupConnectedService("", nullptr, nullptr));
|
|
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()));
|
|
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(*control_interface(), 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();
|
|
string bss_path(
|
|
MakeNewEndpointAndService(0, 0, kNetworkModeAdHoc, nullptr, nullptr));
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(_)).WillOnce(Return(nullptr));
|
|
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, CallWakeOnWiFi_OnScanDone) {
|
|
StartWiFi();
|
|
|
|
// Call WakeOnWiFi::OnNoAutoConnetableServicesAfterScan if we find 0 auto-
|
|
// connectable services.
|
|
EXPECT_CALL(*wifi_provider(), NumAutoConnectableServices())
|
|
.WillOnce(Return(0));
|
|
EXPECT_TRUE(wifi()->IsIdle());
|
|
EXPECT_CALL(*wake_on_wifi_, OnNoAutoConnectableServicesAfterScan(_, _, _));
|
|
ReportScanDone();
|
|
|
|
// If we have 1 or more auto-connectable services, do not call
|
|
// WakeOnWiFi::OnNoAutoConnetableServicesAfterScan.
|
|
EXPECT_CALL(*wifi_provider(), NumAutoConnectableServices())
|
|
.WillOnce(Return(1));
|
|
EXPECT_TRUE(wifi()->IsIdle());
|
|
EXPECT_CALL(*wake_on_wifi_, OnNoAutoConnectableServicesAfterScan(_, _, _))
|
|
.Times(0);
|
|
ReportScanDone();
|
|
|
|
// If the WiFi device is not Idle, do not call
|
|
// WakeOnWiFi::OnNoAutoConnetableServicesAfterScan.
|
|
SetCurrentService(MakeMockService(kSecurityWep));
|
|
EXPECT_FALSE(wifi()->IsIdle());
|
|
EXPECT_CALL(*wifi_provider(), NumAutoConnectableServices())
|
|
.WillOnce(Return(0));
|
|
EXPECT_CALL(*wake_on_wifi_, OnNoAutoConnectableServicesAfterScan(_, _, _))
|
|
.Times(0);
|
|
ReportScanDone();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ScanTimerIdle_FullScan) {
|
|
EnableFullScan();
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
ReportScanDone();
|
|
CancelScanTimer();
|
|
EXPECT_TRUE(GetScanTimer().IsCancelled());
|
|
|
|
EXPECT_CALL(*manager(), OnDeviceGeolocationInfoUpdated(_));
|
|
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();
|
|
InstallMockScanSession();
|
|
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("", nullptr, nullptr);
|
|
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, ScanTimerSuspending) {
|
|
EnableFullScan();
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
ReportScanDone();
|
|
CancelScanTimer();
|
|
EXPECT_TRUE(GetScanTimer().IsCancelled());
|
|
|
|
EXPECT_CALL(*manager(), OnDeviceGeolocationInfoUpdated(_));
|
|
dispatcher_.DispatchPendingEvents();
|
|
EXPECT_CALL(*manager(), IsSuspending()).WillOnce(Return(true));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0);
|
|
FireScanTimer();
|
|
dispatcher_.DispatchPendingEvents();
|
|
EXPECT_TRUE(GetScanTimer().IsCancelled()); // Do not re-arm.
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ScanTimerReconfigured) {
|
|
StartWiFi();
|
|
CancelScanTimer();
|
|
EXPECT_TRUE(GetScanTimer().IsCancelled());
|
|
|
|
SetScanInterval(1, nullptr);
|
|
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, nullptr);
|
|
EXPECT_TRUE(GetScanTimer().IsCancelled());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ScanOnDisconnectWithHidden_FullScan) {
|
|
EnableFullScan();
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
SetupConnectedService("", nullptr, nullptr);
|
|
vector<uint8_t>kSSID(1, 'a');
|
|
ByteArrays ssids;
|
|
ssids.push_back(kSSID);
|
|
ExpectScanIdle();
|
|
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("", nullptr, nullptr);
|
|
InstallMockScanSession();
|
|
vector<uint8_t>kSSID(1, 'a');
|
|
ByteArrays ssids;
|
|
ssids.push_back(kSSID);
|
|
ExpectScanIdle();
|
|
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("", nullptr, nullptr);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0);
|
|
EXPECT_TRUE(IsScanSessionNull());
|
|
EXPECT_CALL(*wifi_provider(), GetHiddenSSIDList())
|
|
.WillRepeatedly(Return(ByteArrays()));
|
|
ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull);
|
|
dispatcher_.DispatchPendingEvents();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, LinkMonitorFailure) {
|
|
ScopedMockLog log;
|
|
auto link_monitor = new StrictMock<MockLinkMonitor>();
|
|
StartWiFi();
|
|
SetLinkMonitor(link_monitor);
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(*link_monitor, IsGatewayFound())
|
|
.WillOnce(Return(false))
|
|
.WillRepeatedly(Return(true));
|
|
|
|
// We never had an ARP reply during this connection, so we assume
|
|
// the problem is gateway, rather than link.
|
|
EXPECT_CALL(log, Log(logging::LOG_INFO, _,
|
|
EndsWith("gateway was never found."))).Times(1);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Reattach()).Times(0);
|
|
OnLinkMonitorFailure();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
|
|
// No supplicant, so we can't Reattach.
|
|
OnSupplicantVanish();
|
|
EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
|
|
EndsWith("Cannot reassociate."))).Times(1);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Reattach()).Times(0);
|
|
OnLinkMonitorFailure();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
|
|
// Normal case: call Reattach.
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
SetCurrentService(service);
|
|
OnSupplicantAppear();
|
|
EXPECT_CALL(log, Log(logging::LOG_INFO, _,
|
|
EndsWith("Called Reattach()."))).Times(1);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Reattach())
|
|
.WillOnce(Return(true));
|
|
OnLinkMonitorFailure();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
|
|
// Service is unreliable, skip reassociate attempt.
|
|
service->set_unreliable(true);
|
|
EXPECT_CALL(log, Log(logging::LOG_INFO, _,
|
|
EndsWith("skipping reassociate attempt."))).Times(1);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Reattach()).Times(0);
|
|
OnLinkMonitorFailure();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, UnreliableLink) {
|
|
StartWiFi();
|
|
SetupConnectedService("", nullptr, nullptr);
|
|
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), SetHT40Enable(_, false)).Times(1);
|
|
OnUnreliableLink();
|
|
Mock::VerifyAndClearExpectations(GetSupplicantInterfaceProxy());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, SuspectCredentialsOpen) {
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
EXPECT_CALL(*service, AddSuspectedCredentialFailure()).Times(0);
|
|
EXPECT_FALSE(SuspectCredentials(service, nullptr));
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, SuspectCredentialsWPA) {
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityWpa);
|
|
ReportStateChanged(WPASupplicant::kInterfaceState4WayHandshake);
|
|
EXPECT_CALL(*service, AddSuspectedCredentialFailure())
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true));
|
|
EXPECT_FALSE(SuspectCredentials(service, nullptr));
|
|
Service::ConnectFailure failure;
|
|
EXPECT_TRUE(SuspectCredentials(service, &failure));
|
|
EXPECT_EQ(Service::kFailureBadPassphrase, failure);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, SuspectCredentialsWEP) {
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityWep);
|
|
ExpectConnecting();
|
|
InitiateConnect(service);
|
|
SetCurrentService(service);
|
|
|
|
// These expectations are very much like SetupConnectedService except
|
|
// that we verify that ResetSupsectCredentialFailures() is not called
|
|
// on the service just because supplicant entered the Completed state.
|
|
EXPECT_CALL(*service, SetState(Service::kStateConfiguring));
|
|
EXPECT_CALL(*service, ResetSuspectedCredentialFailures()).Times(0);
|
|
EXPECT_CALL(*dhcp_provider(), CreateIPv4Config(_, _, _, _))
|
|
.Times(AnyNumber());
|
|
EXPECT_CALL(*dhcp_config_.get(), RequestIP()).Times(AnyNumber());
|
|
EXPECT_CALL(*manager(), device_info()).WillRepeatedly(Return(device_info()));
|
|
EXPECT_CALL(*device_info(), GetByteCounts(_, _, _))
|
|
.WillOnce(DoAll(SetArgumentPointee<2>(0LL), Return(true)));
|
|
ReportStateChanged(WPASupplicant::kInterfaceStateCompleted);
|
|
|
|
Mock::VerifyAndClearExpectations(device_info());
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
// Successful connect.
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), EnableHighBitrates()).Times(1);
|
|
EXPECT_CALL(*service, ResetSuspectedCredentialFailures());
|
|
ReportConnected();
|
|
|
|
EXPECT_CALL(*device_info(), GetByteCounts(_, _, _))
|
|
.WillOnce(DoAll(SetArgumentPointee<2>(1LL), Return(true)))
|
|
.WillOnce(DoAll(SetArgumentPointee<2>(0LL), Return(true)))
|
|
.WillOnce(DoAll(SetArgumentPointee<2>(0LL), Return(true)));
|
|
|
|
// If there was an increased byte-count while we were timing out DHCP,
|
|
// this should be considered a DHCP failure and not a credential failure.
|
|
EXPECT_CALL(*service, ResetSuspectedCredentialFailures()).Times(0);
|
|
EXPECT_CALL(*service, DisconnectWithFailure(Service::kFailureDHCP,
|
|
_,
|
|
HasSubstr("OnIPConfigFailure")));
|
|
ReportIPConfigFailure();
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
// Connection failed during DHCP but service does not (yet) believe this is
|
|
// due to a passphrase issue.
|
|
EXPECT_CALL(*service, AddSuspectedCredentialFailure())
|
|
.WillOnce(Return(false));
|
|
EXPECT_CALL(*service, DisconnectWithFailure(Service::kFailureDHCP,
|
|
_,
|
|
HasSubstr("OnIPConfigFailure")));
|
|
ReportIPConfigFailure();
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
// Connection failed during DHCP and service believes this is due to a
|
|
// passphrase issue.
|
|
EXPECT_CALL(*service, AddSuspectedCredentialFailure())
|
|
.WillOnce(Return(true));
|
|
EXPECT_CALL(*service,
|
|
DisconnectWithFailure(Service::kFailureBadPassphrase,
|
|
_,
|
|
HasSubstr("OnIPConfigFailure")));
|
|
ReportIPConfigFailure();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, SuspectCredentialsEAPInProgress) {
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurity8021x);
|
|
EXPECT_CALL(*eap_state_handler_, is_eap_in_progress())
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true))
|
|
.WillOnce(Return(false))
|
|
.WillOnce(Return(true));
|
|
EXPECT_CALL(*service, AddSuspectedCredentialFailure()).Times(0);
|
|
EXPECT_FALSE(SuspectCredentials(service, nullptr));
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
EXPECT_CALL(*service, AddSuspectedCredentialFailure()).WillOnce(Return(true));
|
|
Service::ConnectFailure failure;
|
|
EXPECT_TRUE(SuspectCredentials(service, &failure));
|
|
EXPECT_EQ(Service::kFailureEAPAuthentication, failure);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
EXPECT_CALL(*service, AddSuspectedCredentialFailure()).Times(0);
|
|
EXPECT_FALSE(SuspectCredentials(service, nullptr));
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
|
|
EXPECT_CALL(*service, AddSuspectedCredentialFailure())
|
|
.WillOnce(Return(false));
|
|
EXPECT_FALSE(SuspectCredentials(service, nullptr));
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, SuspectCredentialsYieldFailureWPA) {
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityWpa);
|
|
SetPendingService(service);
|
|
ReportStateChanged(WPASupplicant::kInterfaceState4WayHandshake);
|
|
|
|
ExpectScanIdle();
|
|
EXPECT_CALL(*service, AddSuspectedCredentialFailure()).WillOnce(Return(true));
|
|
EXPECT_CALL(*service, SetFailure(Service::kFailureBadPassphrase));
|
|
EXPECT_CALL(*service, SetState(Service::kStateIdle));
|
|
ScopedMockLog log;
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith(kErrorBadPassphrase)));
|
|
ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, SuspectCredentialsYieldFailureEAP) {
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurity8021x);
|
|
SetCurrentService(service);
|
|
|
|
ScopedMockLog log;
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(*service, SetState(Service::kStateIdle));
|
|
// 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, AddSuspectedCredentialFailure()).WillOnce(Return(true));
|
|
EXPECT_CALL(*service, SetFailure(Service::kFailureEAPAuthentication));
|
|
EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
|
|
EndsWith(kErrorEapAuthenticationFailed)));
|
|
EXPECT_CALL(*eap_state_handler_, Reset());
|
|
ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ReportConnectedToServiceAfterWake_CallsWakeOnWiFi) {
|
|
EXPECT_CALL(*wake_on_wifi_,
|
|
ReportConnectedToServiceAfterWake(IsConnectedToCurrentService()));
|
|
ReportConnectedToServiceAfterWake();
|
|
}
|
|
|
|
// 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);
|
|
|
|
// After this, the WiFi device should use the normal scan interval.
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(
|
|
_, GetScanInterval() * 1000))
|
|
.Times(kScanTimes - WiFi::kNumFastScanAttempts + 1);
|
|
|
|
for (int i = 0; i < kScanTimes; i++) {
|
|
FireScanTimer();
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(WiFiTimerTest, FastRescan) {
|
|
// This is to cover calls to PostDelayedTask by WakeOnWiFi::StartMetricsTimer.
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _)).Times(AnyNumber());
|
|
// This PostTask is a result of the call to Scan(nullptr), 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));
|
|
StartWiFi();
|
|
|
|
ExpectInitialScanSequence();
|
|
|
|
// If we end up disconnecting, the sequence should repeat.
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(
|
|
_, WiFi::kFastScanIntervalSeconds * 1000));
|
|
RestartFastScanAttempts();
|
|
|
|
ExpectInitialScanSequence();
|
|
}
|
|
|
|
TEST_F(WiFiTimerTest, ReconnectTimer) {
|
|
EXPECT_CALL(mock_dispatcher_, PostTask(_)).Times(AnyNumber());
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _)).Times(AnyNumber());
|
|
StartWiFi();
|
|
SetupConnectedService("", nullptr, nullptr);
|
|
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(WiFiTimerTest, RequestStationInfo) {
|
|
EXPECT_CALL(mock_dispatcher_, PostTask(_)).Times(AnyNumber());
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _)).Times(AnyNumber());
|
|
|
|
// Setup a connected service here while we have the expectations above set.
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service =
|
|
SetupConnectedService("", nullptr, nullptr);
|
|
string connected_bss = GetSupplicantBSS();
|
|
Mock::VerifyAndClearExpectations(&mock_dispatcher_);
|
|
|
|
EXPECT_CALL(netlink_manager_, SendNl80211Message(_, _, _, _)).Times(0);
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _)).Times(0);
|
|
NiceScopedMockLog log;
|
|
|
|
// There is no current_service_.
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("we are not connected")));
|
|
SetCurrentService(nullptr);
|
|
RequestStationInfo();
|
|
|
|
// current_service_ is not connected.
|
|
EXPECT_CALL(*service, IsConnected()).WillOnce(Return(false));
|
|
SetCurrentService(service);
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("we are not connected")));
|
|
RequestStationInfo();
|
|
|
|
// Endpoint does not exist in endpoint_by_rpcid_.
|
|
EXPECT_CALL(*service, IsConnected()).WillRepeatedly(Return(true));
|
|
SetSupplicantBSS("/some/path/that/does/not/exist/in/endpoint_by_rpcid");
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr(
|
|
"Can't get endpoint for current supplicant BSS")));
|
|
RequestStationInfo();
|
|
Mock::VerifyAndClearExpectations(&netlink_manager_);
|
|
Mock::VerifyAndClearExpectations(&mock_dispatcher_);
|
|
|
|
// We successfully trigger a request to get the station and start a timer
|
|
// for the next call.
|
|
EXPECT_CALL(netlink_manager_, SendNl80211Message(
|
|
IsNl80211Command(kNl80211FamilyId, NL80211_CMD_GET_STATION), _, _, _));
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(
|
|
_, WiFi::kRequestStationInfoPeriodSeconds * 1000));
|
|
SetSupplicantBSS(connected_bss);
|
|
RequestStationInfo();
|
|
|
|
// Now test that a properly formatted New Station message updates strength.
|
|
NewStationMessage new_station;
|
|
new_station.attributes()->CreateRawAttribute(NL80211_ATTR_MAC, "BSSID");
|
|
|
|
// Confirm that up until now no link statistics exist.
|
|
KeyValueStore link_statistics = GetLinkStatistics();
|
|
EXPECT_TRUE(link_statistics.IsEmpty());
|
|
|
|
// Use a reference to the endpoint instance in the WiFi device instead of
|
|
// the copy returned by SetupConnectedService().
|
|
WiFiEndpointRefPtr endpoint = GetEndpointMap().begin()->second;
|
|
new_station.attributes()->SetRawAttributeValue(
|
|
NL80211_ATTR_MAC, ByteString::CreateFromHexString(endpoint->bssid_hex()));
|
|
new_station.attributes()->CreateNestedAttribute(
|
|
NL80211_ATTR_STA_INFO, "Station Info");
|
|
AttributeListRefPtr station_info;
|
|
new_station.attributes()->GetNestedAttributeList(
|
|
NL80211_ATTR_STA_INFO, &station_info);
|
|
station_info->CreateU8Attribute(NL80211_STA_INFO_SIGNAL, "Signal");
|
|
const int kSignalValue = -20;
|
|
station_info->SetU8AttributeValue(NL80211_STA_INFO_SIGNAL, kSignalValue);
|
|
station_info->CreateU8Attribute(NL80211_STA_INFO_SIGNAL_AVG, "SignalAverage");
|
|
const int kSignalAvgValue = -40;
|
|
station_info->SetU8AttributeValue(NL80211_STA_INFO_SIGNAL_AVG,
|
|
kSignalAvgValue);
|
|
station_info->CreateU32Attribute(NL80211_STA_INFO_INACTIVE_TIME,
|
|
"InactiveTime");
|
|
const int32_t kInactiveTime = 100;
|
|
station_info->SetU32AttributeValue(NL80211_STA_INFO_INACTIVE_TIME,
|
|
kInactiveTime);
|
|
station_info->CreateU32Attribute(NL80211_STA_INFO_RX_PACKETS,
|
|
"ReceivedSuccesses");
|
|
const int32_t kReceiveSuccesses = 200;
|
|
station_info->SetU32AttributeValue(NL80211_STA_INFO_RX_PACKETS,
|
|
kReceiveSuccesses);
|
|
station_info->CreateU32Attribute(NL80211_STA_INFO_TX_FAILED,
|
|
"TransmitFailed");
|
|
const int32_t kTransmitFailed = 300;
|
|
station_info->SetU32AttributeValue(NL80211_STA_INFO_TX_FAILED,
|
|
kTransmitFailed);
|
|
station_info->CreateU32Attribute(NL80211_STA_INFO_TX_PACKETS,
|
|
"TransmitSuccesses");
|
|
const int32_t kTransmitSuccesses = 400;
|
|
station_info->SetU32AttributeValue(NL80211_STA_INFO_TX_PACKETS,
|
|
kTransmitSuccesses);
|
|
station_info->CreateU32Attribute(NL80211_STA_INFO_TX_RETRIES,
|
|
"TransmitRetries");
|
|
const int32_t kTransmitRetries = 500;
|
|
station_info->SetU32AttributeValue(NL80211_STA_INFO_TX_RETRIES,
|
|
kTransmitRetries);
|
|
station_info->CreateNestedAttribute(NL80211_STA_INFO_TX_BITRATE,
|
|
"Bitrate Info");
|
|
|
|
// Embed transmit bitrate info within the station info element.
|
|
AttributeListRefPtr bitrate_info;
|
|
station_info->GetNestedAttributeList(
|
|
NL80211_STA_INFO_TX_BITRATE, &bitrate_info);
|
|
bitrate_info->CreateU16Attribute(NL80211_RATE_INFO_BITRATE, "Bitrate");
|
|
const int16_t kBitrate = 6005;
|
|
bitrate_info->SetU16AttributeValue(NL80211_RATE_INFO_BITRATE, kBitrate);
|
|
bitrate_info->CreateU8Attribute(NL80211_RATE_INFO_MCS, "MCS");
|
|
const int16_t kMCS = 7;
|
|
bitrate_info->SetU8AttributeValue(NL80211_RATE_INFO_MCS, kMCS);
|
|
bitrate_info->CreateFlagAttribute(NL80211_RATE_INFO_40_MHZ_WIDTH, "HT40");
|
|
bitrate_info->SetFlagAttributeValue(NL80211_RATE_INFO_40_MHZ_WIDTH, true);
|
|
bitrate_info->CreateFlagAttribute(NL80211_RATE_INFO_SHORT_GI, "SGI");
|
|
bitrate_info->SetFlagAttributeValue(NL80211_RATE_INFO_SHORT_GI, false);
|
|
station_info->SetNestedAttributeHasAValue(NL80211_STA_INFO_TX_BITRATE);
|
|
|
|
new_station.attributes()->SetNestedAttributeHasAValue(NL80211_ATTR_STA_INFO);
|
|
|
|
EXPECT_NE(kSignalValue, endpoint->signal_strength());
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointUpdated(EndpointMatch(endpoint)));
|
|
EXPECT_CALL(*metrics(), NotifyWifiTxBitrate(kBitrate/10));
|
|
AttributeListConstRefPtr station_info_prime;
|
|
ReportReceivedStationInfo(new_station);
|
|
EXPECT_EQ(kSignalValue, endpoint->signal_strength());
|
|
|
|
link_statistics = GetLinkStatistics();
|
|
ASSERT_FALSE(link_statistics.IsEmpty());
|
|
ASSERT_TRUE(link_statistics.ContainsInt(kLastReceiveSignalDbmProperty));
|
|
EXPECT_EQ(kSignalValue,
|
|
link_statistics.GetInt(kLastReceiveSignalDbmProperty));
|
|
ASSERT_TRUE(link_statistics.ContainsInt(kAverageReceiveSignalDbmProperty));
|
|
EXPECT_EQ(kSignalAvgValue,
|
|
link_statistics.GetInt(kAverageReceiveSignalDbmProperty));
|
|
ASSERT_TRUE(link_statistics.ContainsUint(kInactiveTimeMillisecondsProperty));
|
|
EXPECT_EQ(kInactiveTime,
|
|
link_statistics.GetUint(kInactiveTimeMillisecondsProperty));
|
|
ASSERT_TRUE(link_statistics.ContainsUint(kPacketReceiveSuccessesProperty));
|
|
EXPECT_EQ(kReceiveSuccesses,
|
|
link_statistics.GetUint(kPacketReceiveSuccessesProperty));
|
|
ASSERT_TRUE(link_statistics.ContainsUint(kPacketTransmitFailuresProperty));
|
|
EXPECT_EQ(kTransmitFailed,
|
|
link_statistics.GetUint(kPacketTransmitFailuresProperty));
|
|
ASSERT_TRUE(link_statistics.ContainsUint(kPacketTransmitSuccessesProperty));
|
|
EXPECT_EQ(kTransmitSuccesses,
|
|
link_statistics.GetUint(kPacketTransmitSuccessesProperty));
|
|
ASSERT_TRUE(link_statistics.ContainsUint(kTransmitRetriesProperty));
|
|
EXPECT_EQ(kTransmitRetries,
|
|
link_statistics.GetUint(kTransmitRetriesProperty));
|
|
EXPECT_EQ(StringPrintf("%d.%d MBit/s MCS %d 40MHz",
|
|
kBitrate / 10, kBitrate % 10, kMCS),
|
|
link_statistics.LookupString(kTransmitBitrateProperty, ""));
|
|
|
|
// New station info with VHT rate parameters.
|
|
NewStationMessage new_vht_station;
|
|
new_vht_station.attributes()->CreateRawAttribute(NL80211_ATTR_MAC, "BSSID");
|
|
|
|
new_vht_station.attributes()->SetRawAttributeValue(
|
|
NL80211_ATTR_MAC, ByteString::CreateFromHexString(endpoint->bssid_hex()));
|
|
new_vht_station.attributes()->CreateNestedAttribute(
|
|
NL80211_ATTR_STA_INFO, "Station Info");
|
|
new_vht_station.attributes()->GetNestedAttributeList(
|
|
NL80211_ATTR_STA_INFO, &station_info);
|
|
station_info->CreateU8Attribute(NL80211_STA_INFO_SIGNAL, "Signal");
|
|
station_info->SetU8AttributeValue(NL80211_STA_INFO_SIGNAL, kSignalValue);
|
|
station_info->CreateNestedAttribute(NL80211_STA_INFO_TX_BITRATE,
|
|
"Bitrate Info");
|
|
|
|
// Embed transmit VHT bitrate info within the station info element.
|
|
station_info->GetNestedAttributeList(
|
|
NL80211_STA_INFO_TX_BITRATE, &bitrate_info);
|
|
bitrate_info->CreateU32Attribute(NL80211_RATE_INFO_BITRATE32, "Bitrate32");
|
|
const int32_t kVhtBitrate = 70000;
|
|
bitrate_info->SetU32AttributeValue(NL80211_RATE_INFO_BITRATE32, kVhtBitrate);
|
|
bitrate_info->CreateU8Attribute(NL80211_RATE_INFO_VHT_MCS, "VHT-MCS");
|
|
const int8_t kVhtMCS = 7;
|
|
bitrate_info->SetU8AttributeValue(NL80211_RATE_INFO_VHT_MCS, kVhtMCS);
|
|
bitrate_info->CreateU8Attribute(NL80211_RATE_INFO_VHT_NSS, "VHT-NSS");
|
|
const int8_t kVhtNSS = 1;
|
|
bitrate_info->SetU8AttributeValue(NL80211_RATE_INFO_VHT_NSS, kVhtNSS);
|
|
bitrate_info->CreateFlagAttribute(NL80211_RATE_INFO_80_MHZ_WIDTH, "VHT80");
|
|
bitrate_info->SetFlagAttributeValue(NL80211_RATE_INFO_80_MHZ_WIDTH, true);
|
|
bitrate_info->CreateFlagAttribute(NL80211_RATE_INFO_SHORT_GI, "SGI");
|
|
bitrate_info->SetFlagAttributeValue(NL80211_RATE_INFO_SHORT_GI, false);
|
|
station_info->SetNestedAttributeHasAValue(NL80211_STA_INFO_TX_BITRATE);
|
|
|
|
new_vht_station.attributes()->SetNestedAttributeHasAValue(
|
|
NL80211_ATTR_STA_INFO);
|
|
|
|
EXPECT_CALL(*metrics(), NotifyWifiTxBitrate(kVhtBitrate/10));
|
|
|
|
ReportReceivedStationInfo(new_vht_station);
|
|
|
|
link_statistics = GetLinkStatistics();
|
|
EXPECT_EQ(StringPrintf("%d.%d MBit/s VHT-MCS %d 80MHz VHT-NSS %d",
|
|
kVhtBitrate / 10, kVhtBitrate % 10, kVhtMCS, kVhtNSS),
|
|
link_statistics.LookupString(kTransmitBitrateProperty, ""));
|
|
}
|
|
|
|
TEST_F(WiFiTimerTest, ResumeDispatchesConnectivityReportTask) {
|
|
EXPECT_CALL(mock_dispatcher_, PostTask(_)).Times(AnyNumber());
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _)).Times(AnyNumber());
|
|
StartWiFi();
|
|
SetupConnectedService("", nullptr, nullptr);
|
|
EXPECT_CALL(
|
|
mock_dispatcher_,
|
|
PostDelayedTask(_, WiFi::kPostWakeConnectivityReportDelayMilliseconds));
|
|
OnAfterResume();
|
|
}
|
|
|
|
TEST_F(WiFiTimerTest, StartScanTimer_ReturnsImmediately) {
|
|
Error e;
|
|
// Return immediately if scan interval is 0.
|
|
SetScanInterval(0, &e);
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _)).Times(0);
|
|
StartScanTimer();
|
|
}
|
|
|
|
TEST_F(WiFiTimerTest, StartScanTimer_HaveFastScansRemaining) {
|
|
Error e;
|
|
const int scan_interval = 10;
|
|
SetScanInterval(scan_interval, &e);
|
|
SetFastScansRemaining(1);
|
|
EXPECT_CALL(mock_dispatcher_,
|
|
PostDelayedTask(_, WiFi::kFastScanIntervalSeconds * 1000));
|
|
StartScanTimer();
|
|
}
|
|
|
|
TEST_F(WiFiTimerTest, StartScanTimer_NoFastScansRemaining) {
|
|
Error e;
|
|
const int scan_interval = 10;
|
|
SetScanInterval(scan_interval, &e);
|
|
SetFastScansRemaining(0);
|
|
EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, scan_interval * 1000));
|
|
StartScanTimer();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, EAPCertification) {
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurity8021x);
|
|
EXPECT_CALL(*service, AddEAPCertification(_, _)).Times(0);
|
|
|
|
ScopedMockLog log;
|
|
EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith("no current service.")));
|
|
KeyValueStore 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_t kDepth = 123;
|
|
args.SetUint(WPASupplicant::kInterfacePropertyDepth, kDepth);
|
|
|
|
EXPECT_CALL(log,
|
|
Log(logging::LOG_ERROR, _, EndsWith("no subject parameter.")));
|
|
ReportCertification(args);
|
|
Mock::VerifyAndClearExpectations(&log);
|
|
|
|
const string kSubject("subject");
|
|
args.SetString(WPASupplicant::kInterfacePropertySubject, kSubject);
|
|
EXPECT_CALL(*service, AddEAPCertification(kSubject, kDepth)).Times(1);
|
|
ReportCertification(args);
|
|
}
|
|
|
|
TEST_F(WiFiTimerTest, ScanDoneDispatchesTasks) {
|
|
// Dispatch WiFi::ScanFailedTask if scan failed.
|
|
EXPECT_TRUE(ScanFailedCallbackIsCancelled());
|
|
EXPECT_CALL(mock_dispatcher_,
|
|
PostDelayedTask(_, WiFi::kPostScanFailedDelayMilliseconds));
|
|
ScanDone(false);
|
|
EXPECT_FALSE(ScanFailedCallbackIsCancelled());
|
|
|
|
// Dispatch WiFi::ScanDoneTask if scan succeeded, and cancel the scan failed
|
|
// callback if has been dispatched.
|
|
EXPECT_CALL(mock_dispatcher_, PostTask(_));
|
|
ScanDone(true);
|
|
EXPECT_TRUE(ScanFailedCallbackIsCancelled());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, EAPEvent) {
|
|
StartWiFi();
|
|
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(kSecurity8021x);
|
|
EXPECT_CALL(*service, SetFailure(_)).Times(0);
|
|
EXPECT_CALL(*eap_state_handler_, ParseStatus(kEAPStatus, kEAPParameter, _));
|
|
SetCurrentService(service);
|
|
ReportEAPEvent(kEAPStatus, kEAPParameter);
|
|
Mock::VerifyAndClearExpectations(service.get());
|
|
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,
|
|
_,
|
|
HasSubstr("EAPEventTask")));
|
|
ReportEAPEvent(kEAPStatus, kEAPParameter);
|
|
|
|
MockEapCredentials* eap = new MockEapCredentials();
|
|
service->eap_.reset(eap); // Passes ownership.
|
|
const char kNetworkRpcId[] = "/service/network/rpcid";
|
|
SetServiceNetworkRpcId(service, kNetworkRpcId);
|
|
EXPECT_CALL(*eap_state_handler_, ParseStatus(kEAPStatus, kEAPParameter, _))
|
|
.WillOnce(DoAll(SetArgumentPointee<2>(Service::kFailurePinMissing),
|
|
Return(false)));
|
|
// We need a real string object since it will be returned by reference below.
|
|
const string kEmptyPin;
|
|
EXPECT_CALL(*eap, pin()).WillOnce(ReturnRef(kEmptyPin));
|
|
EXPECT_CALL(*service, DisconnectWithFailure(Service::kFailurePinMissing,
|
|
_,
|
|
HasSubstr("EAPEventTask")));
|
|
ReportEAPEvent(kEAPStatus, kEAPParameter);
|
|
|
|
EXPECT_CALL(*eap_state_handler_, ParseStatus(kEAPStatus, kEAPParameter, _))
|
|
.WillOnce(DoAll(SetArgumentPointee<2>(Service::kFailurePinMissing),
|
|
Return(false)));
|
|
// We need a real string object since it will be returned by reference below.
|
|
const string kPin("000000");
|
|
EXPECT_CALL(*eap, pin()).WillOnce(ReturnRef(kPin));
|
|
EXPECT_CALL(*service, DisconnectWithFailure(_, _, _)).Times(0);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(),
|
|
NetworkReply(StrEq(kNetworkRpcId),
|
|
StrEq(WPASupplicant::kEAPRequestedParameterPIN),
|
|
Ref(kPin)));
|
|
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();
|
|
}
|
|
|
|
struct BSS {
|
|
string bsspath;
|
|
string ssid;
|
|
string bssid;
|
|
int16_t signal_strength;
|
|
uint16_t 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_;
|
|
|
|
// 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(
|
|
DoAll(SetArgumentPointee<0>(string(WPASupplicant::kDebugLevelDebug)),
|
|
Return(true)));
|
|
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(
|
|
DoAll(SetArgumentPointee<0>(string(WPASupplicant::kDebugLevelError)),
|
|
Return(true)))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(string(WPASupplicant::kDebugLevelError)),
|
|
Return(true)))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(
|
|
string(WPASupplicant::kDebugLevelExcessive)),
|
|
Return(true)))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(
|
|
string(WPASupplicant::kDebugLevelExcessive)),
|
|
Return(true)))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(
|
|
string(WPASupplicant::kDebugLevelMsgDump)),
|
|
Return(true)))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(
|
|
string(WPASupplicant::kDebugLevelMsgDump)),
|
|
Return(true)))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(
|
|
string(WPASupplicant::kDebugLevelWarning)),
|
|
Return(true)))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(
|
|
string(WPASupplicant::kDebugLevelWarning)),
|
|
Return(true)));
|
|
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(
|
|
DoAll(SetArgumentPointee<0>(string(WPASupplicant::kDebugLevelDebug)),
|
|
Return(true)));
|
|
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(
|
|
DoAll(SetArgumentPointee<0>(string(WPASupplicant::kDebugLevelInfo)),
|
|
Return(true)));
|
|
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(
|
|
DoAll(SetArgumentPointee<0>(string(WPASupplicant::kDebugLevelDebug)),
|
|
Return(true)))
|
|
.WillOnce(
|
|
DoAll(SetArgumentPointee<0>(string(WPASupplicant::kDebugLevelInfo)),
|
|
Return(true)));
|
|
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_t 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_t 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) {
|
|
StartScan(WiFi::kScanMethodFull);
|
|
ReportScanDone();
|
|
ExpectScanStop();
|
|
ExpectFoundNothing();
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(10);
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("FULL_NOCONNECTION ->")));
|
|
EXPECT_CALL(*manager(), OnDeviceGeolocationInfoUpdated(_));
|
|
dispatcher_.DispatchPendingEvents(); // Launch UpdateScanStateAfterScanDone
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, FullScanConnectingToConnected) {
|
|
StartScan(WiFi::kScanMethodFull);
|
|
WiFiEndpointRefPtr endpoint;
|
|
string bss_path;
|
|
MockWiFiServiceRefPtr service = AttemptConnection(WiFi::kScanMethodFull,
|
|
&endpoint,
|
|
&bss_path);
|
|
|
|
// Complete the connection.
|
|
ExpectConnected();
|
|
EXPECT_CALL(*service, NotifyCurrentEndpoint(EndpointMatch(endpoint)));
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(10);
|
|
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) {
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
WiFiEndpointRefPtr endpoint;
|
|
string bss_path;
|
|
MockWiFiServiceRefPtr service = AttemptConnection(
|
|
WiFi::kScanMethodProgressive, &endpoint, &bss_path);
|
|
|
|
// Complete the connection.
|
|
ExpectConnected();
|
|
EXPECT_CALL(*service, NotifyCurrentEndpoint(EndpointMatch(endpoint)));
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(10);
|
|
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, ProgressiveScanConnectingToNotFound) {
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
WiFiEndpointRefPtr endpoint;
|
|
MockWiFiServiceRefPtr service = AttemptConnection(
|
|
WiFi::kScanMethodProgressive, &endpoint, nullptr);
|
|
|
|
// Simulate connection timeout.
|
|
ExpectFoundNothing();
|
|
EXPECT_CALL(*service,
|
|
NotifyCurrentEndpoint(EndpointMatch(endpoint))).Times(0);
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(10);
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log,
|
|
Log(_, _, HasSubstr("-> PROGRESSIVE_FINISHED_NOCONNECTION")));
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectFinished(_)).Times(0);
|
|
TimeoutPendingConnection();
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ScanStateUma) {
|
|
EXPECT_CALL(*metrics(), SendEnumToUMA(Metrics::kMetricScanResult, _, _)).
|
|
Times(0);
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanStarted(_));
|
|
SetScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive, __func__);
|
|
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanFinished(_));
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectStarted(_, _));
|
|
SetScanState(WiFi::kScanConnecting, WiFi::kScanMethodProgressive, __func__);
|
|
|
|
ExpectScanIdle(); // After connected.
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectFinished(_));
|
|
EXPECT_CALL(*metrics(), SendEnumToUMA(Metrics::kMetricScanResult, _, _));
|
|
SetScanState(WiFi::kScanConnected, WiFi::kScanMethodProgressive, __func__);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ScanStateNotScanningNoUma) {
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanStarted(_)).Times(0);
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectStarted(_, _));
|
|
SetScanState(WiFi::kScanConnecting, WiFi::kScanMethodNone, __func__);
|
|
|
|
ExpectScanIdle(); // After connected.
|
|
EXPECT_CALL(*metrics(), NotifyDeviceConnectFinished(_));
|
|
EXPECT_CALL(*metrics(), SendEnumToUMA(Metrics::kMetricScanResult, _, _)).
|
|
Times(0);
|
|
SetScanState(WiFi::kScanConnected, WiFi::kScanMethodNone, __func__);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ConnectToServiceNotPending) {
|
|
// Test for SetPendingService(nullptr), condition a)
|
|
// |ConnectTo|->|DisconnectFrom|.
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
|
|
// Setup pending service.
|
|
ExpectScanStop();
|
|
ExpectConnecting();
|
|
MockWiFiServiceRefPtr service_pending(
|
|
SetupConnectingService("", nullptr, nullptr));
|
|
EXPECT_EQ(service_pending.get(), GetPendingService().get());
|
|
|
|
// ConnectTo a different service than the pending one.
|
|
ExpectConnecting();
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Disconnect());
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(10);
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("-> TRANSITION_TO_CONNECTING")));
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("-> PROGRESSIVE_CONNECTING")));
|
|
MockWiFiServiceRefPtr service_connecting(
|
|
SetupConnectingService("", nullptr, nullptr));
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
EXPECT_EQ(service_connecting.get(), GetPendingService().get());
|
|
EXPECT_EQ(nullptr, GetCurrentService().get());
|
|
VerifyScanState(WiFi::kScanConnecting, WiFi::kScanMethodProgressive);
|
|
|
|
ExpectScanIdle(); // To silence messages from the destructor.
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ConnectToWithError) {
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
|
|
ExpectScanIdle();
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), AddNetwork(_, _)).
|
|
WillOnce(Return(false));
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanFinished(_)).Times(0);
|
|
EXPECT_CALL(*metrics(), SendEnumToUMA(Metrics::kMetricScanResult, _, _)).
|
|
Times(0);
|
|
EXPECT_CALL(*adaptor_, EmitBoolChanged(kScanningProperty, false));
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
EXPECT_CALL(*service, GetSupplicantConfigurationParameters());
|
|
InitiateConnect(service);
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
EXPECT_TRUE(IsScanSessionNull());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ScanStateHandleDisconnect) {
|
|
// Test for SetPendingService(nullptr), condition d) Disconnect while
|
|
// scanning.
|
|
|
|
// Start scanning.
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
|
|
// Set the pending service.
|
|
ReportScanDoneKeepScanSession();
|
|
ExpectScanStop();
|
|
ExpectConnecting();
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityNone);
|
|
SetPendingService(service);
|
|
VerifyScanState(WiFi::kScanConnecting, WiFi::kScanMethodProgressive);
|
|
|
|
// Disconnect from the pending service.
|
|
ExpectScanIdle();
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanFinished(_)).Times(0);
|
|
EXPECT_CALL(*metrics(), SendEnumToUMA(Metrics::kMetricScanResult, _, _)).
|
|
Times(0);
|
|
ReportCurrentBSSChanged(WPASupplicant::kCurrentBSSNull);
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ConnectWhileNotScanning) {
|
|
// Setup WiFi but terminate scan.
|
|
EXPECT_CALL(*adaptor_, EmitBoolChanged(kPoweredProperty, _)).
|
|
Times(AnyNumber());
|
|
|
|
ExpectScanStart(WiFi::kScanMethodProgressive, false);
|
|
StartWiFi();
|
|
dispatcher_.DispatchPendingEvents();
|
|
|
|
ExpectScanStop();
|
|
ExpectFoundNothing();
|
|
ReportScanDone();
|
|
dispatcher_.DispatchPendingEvents();
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
|
|
// Connecting.
|
|
ExpectConnecting();
|
|
EXPECT_CALL(*metrics(), NotifyDeviceScanStarted(_)).Times(0);
|
|
WiFiEndpointRefPtr endpoint;
|
|
string bss_path;
|
|
NiceScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(10);
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("-> TRANSITION_TO_CONNECTING"))).
|
|
Times(0);
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("-> CONNECTING (not scan related)")));
|
|
MockWiFiServiceRefPtr service =
|
|
SetupConnectingService("", &endpoint, &bss_path);
|
|
|
|
// Connected.
|
|
ExpectConnected();
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("-> CONNECTED (not scan related")));
|
|
ReportCurrentBSSChanged(bss_path);
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, BackgroundScan) {
|
|
StartWiFi();
|
|
SetupConnectedService("", nullptr, nullptr);
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(1);
|
|
TriggerScan(WiFi::kScanMethodFull);
|
|
dispatcher_.DispatchPendingEvents();
|
|
VerifyScanState(WiFi::kScanBackgroundScanning, WiFi::kScanMethodFull);
|
|
|
|
ReportScanDone();
|
|
EXPECT_CALL(*manager(), OnDeviceGeolocationInfoUpdated(_));
|
|
dispatcher_.DispatchPendingEvents(); // Launch UpdateScanStateAfterScanDone
|
|
VerifyScanState(WiFi::kScanIdle, WiFi::kScanMethodNone);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ProgressiveScanDuringFull) {
|
|
StartScan(WiFi::kScanMethodFull);
|
|
|
|
// Now, try to slam-in a progressive scan.
|
|
EXPECT_CALL(*scan_session_, InitiateScan()).Times(0);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0);
|
|
TriggerScan(WiFi::kScanMethodProgressive);
|
|
dispatcher_.DispatchPendingEvents();
|
|
VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodFull);
|
|
|
|
// And, for the destructor.
|
|
ExpectScanStop();
|
|
ExpectScanIdle();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, FullScanDuringProgressive) {
|
|
StartScan(WiFi::kScanMethodProgressive);
|
|
|
|
// Now, try to slam-in a full scan.
|
|
EXPECT_CALL(*scan_session_, InitiateScan()).Times(0);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), Scan(_)).Times(0);
|
|
TriggerScan(WiFi::kScanMethodFull);
|
|
dispatcher_.DispatchPendingEvents();
|
|
VerifyScanState(WiFi::kScanScanning, WiFi::kScanMethodProgressive);
|
|
|
|
// And, for the destructor.
|
|
ExpectScanStop();
|
|
ExpectScanIdle();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, TDLSDiscoverResponse) {
|
|
const char kPeer[] = "peer";
|
|
MockTDLSManager* tdls_manager = new StrictMock<MockTDLSManager>();
|
|
SetTDLSManager(tdls_manager);
|
|
|
|
EXPECT_CALL(*tdls_manager, OnDiscoverResponseReceived(kPeer));
|
|
TDLSDiscoverResponse(kPeer);
|
|
Mock::VerifyAndClearExpectations(tdls_manager);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, PerformTDLSOperation) {
|
|
const char kPeerMac[] = "00:11:22:33:44:55";
|
|
MockTDLSManager* tdls_manager = new StrictMock<MockTDLSManager>();
|
|
SetTDLSManager(tdls_manager);
|
|
|
|
Error error;
|
|
// No address resolution is performed since MAC address is provided.
|
|
EXPECT_CALL(*tdls_manager,
|
|
PerformOperation(kPeerMac, kTDLSStatusOperation, &error))
|
|
.WillOnce(Return(kTDLSConnectedState));
|
|
EXPECT_EQ(kTDLSConnectedState,
|
|
PerformTDLSOperation(kTDLSStatusOperation, kPeerMac, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, OnNewWiphy) {
|
|
NewWiphyMessage new_wiphy_message;
|
|
NetlinkPacket packet(kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg));
|
|
new_wiphy_message.InitFromPacket(&packet, NetlinkMessage::MessageContext());
|
|
EXPECT_CALL(*mac80211_monitor(), Start(_));
|
|
EXPECT_CALL(*wake_on_wifi_, ParseWakeOnWiFiCapabilities(_));
|
|
EXPECT_CALL(*wake_on_wifi_, OnWiphyIndexReceived(kNewWiphyNlMsg_WiphyIndex));
|
|
GetAllScanFrequencies()->clear();
|
|
OnNewWiphy(new_wiphy_message);
|
|
EXPECT_EQ(arraysize(kNewWiphyNlMsg_UniqueFrequencies),
|
|
GetAllScanFrequencies()->size());
|
|
for (uint16_t freq : kNewWiphyNlMsg_UniqueFrequencies) {
|
|
EXPECT_TRUE(GetAllScanFrequencies()->find(freq) !=
|
|
GetAllScanFrequencies()->end());
|
|
}
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, StateChangedUpdatesMac80211Monitor) {
|
|
EXPECT_CALL(*mac80211_monitor(), UpdateConnectedState(true)).Times(2);
|
|
ReportStateChanged(WPASupplicant::kInterfaceStateCompleted);
|
|
ReportStateChanged(WPASupplicant::kInterfaceState4WayHandshake);
|
|
|
|
EXPECT_CALL(*mac80211_monitor(), UpdateConnectedState(false));
|
|
ReportStateChanged(WPASupplicant::kInterfaceStateAssociating);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, OnIPConfigUpdated_InvokesOnConnectedAndReachable) {
|
|
ScopedMockLog log;
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(3);
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("IPv4 DHCP lease obtained")));
|
|
EXPECT_CALL(*wake_on_wifi_, OnConnectedAndReachable(_, _));
|
|
EXPECT_CALL(*manager(), device_info()).WillOnce(Return(device_info()));
|
|
ReportIPConfigComplete();
|
|
|
|
// We should not call WakeOnWiFi::OnConnectedAndReachable if we are not
|
|
// actually connected to a service.
|
|
SetCurrentService(nullptr);
|
|
EXPECT_CALL(*wake_on_wifi_, OnConnectedAndReachable(_, _)).Times(0);
|
|
ReportIPv6ConfigComplete();
|
|
|
|
// If we are actually connected to a service when our IPv6 configuration is
|
|
// updated, we should call WakeOnWiFi::OnConnectedAndReachable.
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurity8021x);
|
|
EXPECT_CALL(*service, IsConnected()).WillOnce(Return(true));
|
|
SetCurrentService(service);
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("IPv6 configuration obtained")));
|
|
EXPECT_CALL(*wake_on_wifi_, OnConnectedAndReachable(_, _));
|
|
ReportIPv6ConfigComplete();
|
|
|
|
// Do not call WakeOnWiFi::OnConnectedAndReachable if the IP config update was
|
|
// triggered by a gateway ARP.
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("Gateway ARP received")));
|
|
EXPECT_CALL(*wake_on_wifi_, OnConnectedAndReachable(_, _)).Times(0);
|
|
ReportIPConfigCompleteGatewayArpReceived();
|
|
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, OnBeforeSuspend_CallsWakeOnWiFi) {
|
|
SetWiFiEnabled(true);
|
|
EXPECT_CALL(
|
|
*wake_on_wifi_,
|
|
OnBeforeSuspend(IsConnectedToCurrentService(), _, _, _, _, _, _));
|
|
EXPECT_CALL(*this, SuspendCallback(_)).Times(0);
|
|
OnBeforeSuspend();
|
|
|
|
SetWiFiEnabled(false);
|
|
EXPECT_CALL(*wake_on_wifi_,
|
|
OnBeforeSuspend(IsConnectedToCurrentService(), _, _, _, _, _, _))
|
|
.Times(0);
|
|
EXPECT_CALL(*this, SuspendCallback(ErrorTypeIs(Error::kSuccess)));
|
|
OnBeforeSuspend();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, OnDarkResume_CallsWakeOnWiFi) {
|
|
SetWiFiEnabled(true);
|
|
EXPECT_CALL(*wake_on_wifi_,
|
|
OnDarkResume(IsConnectedToCurrentService(), _, _, _, _, _));
|
|
EXPECT_CALL(*this, SuspendCallback(_)).Times(0);
|
|
OnDarkResume();
|
|
|
|
SetWiFiEnabled(false);
|
|
EXPECT_CALL(*wake_on_wifi_,
|
|
OnDarkResume(IsConnectedToCurrentService(), _, _, _, _, _))
|
|
.Times(0);
|
|
EXPECT_CALL(*this, SuspendCallback(ErrorTypeIs(Error::kSuccess)));
|
|
OnDarkResume();
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, RemoveSupplicantNetworks) {
|
|
StartWiFi();
|
|
MockWiFiServiceRefPtr service1 = MakeMockService(kSecurity8021x);
|
|
MockWiFiServiceRefPtr service2 = MakeMockService(kSecurity8021x);
|
|
const char kNetworkRpcId1[] = "/service/network/rpcid1";
|
|
const char kNetworkRpcId2[] = "/service/network/rpcid2";
|
|
string path1(kNetworkRpcId1);
|
|
string path2(kNetworkRpcId2);
|
|
SetServiceNetworkRpcId(service1, kNetworkRpcId1);
|
|
SetServiceNetworkRpcId(service2, kNetworkRpcId2);
|
|
ASSERT_FALSE(RpcIdByServiceIsEmpty());
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(path1));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), RemoveNetwork(path2));
|
|
RemoveSupplicantNetworks();
|
|
ASSERT_TRUE(RpcIdByServiceIsEmpty());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, InitiateScan_Idle) {
|
|
ScopedMockLog log;
|
|
Device::ScanType scan_type = Device::kFullScan;
|
|
ASSERT_TRUE(wifi()->IsIdle());
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log, Log(_, _, ContainsRegex("Scan.* \\[full\\]")));
|
|
InitiateScan(scan_type);
|
|
|
|
scan_type = Device::kProgressiveScan;
|
|
ASSERT_TRUE(wifi()->IsIdle());
|
|
EXPECT_CALL(log, Log(_, _, ContainsRegex("Scan.* \\[progressive\\]")));
|
|
InitiateScan(scan_type);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, InitiateScan_NotIdle) {
|
|
const Device::ScanType scan_type = Device::kFullScan;
|
|
ScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(1);
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityWpa);
|
|
SetPendingService(service);
|
|
EXPECT_FALSE(wifi()->IsIdle());
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(
|
|
log,
|
|
Log(_, _, HasSubstr("skipping scan, already connecting or connected.")));
|
|
InitiateScan(scan_type);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, InitiateScanInDarkResume_Idle) {
|
|
const WiFi::FreqSet freqs;
|
|
StartWiFi();
|
|
manager()->set_suppress_autoconnect(false);
|
|
ASSERT_TRUE(wifi()->IsIdle());
|
|
EXPECT_CALL(netlink_manager_,
|
|
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
|
|
TriggerScanMessage::kCommand),
|
|
_, _, _));
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), FlushBSS(0));
|
|
InitiateScanInDarkResume(freqs);
|
|
EXPECT_TRUE(manager()->suppress_autoconnect());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, InitiateScanInDarkResume_NotIdle) {
|
|
const WiFi::FreqSet freqs;
|
|
ScopedMockLog log;
|
|
MockWiFiServiceRefPtr service = MakeMockService(kSecurityWpa);
|
|
SetPendingService(service);
|
|
manager()->set_suppress_autoconnect(false);
|
|
EXPECT_FALSE(wifi()->IsIdle());
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(
|
|
log,
|
|
Log(_, _, HasSubstr("skipping scan, already connecting or connected.")));
|
|
EXPECT_CALL(netlink_manager_,
|
|
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
|
|
TriggerScanMessage::kCommand),
|
|
_, _, _)).Times(0);
|
|
EXPECT_CALL(*GetSupplicantInterfaceProxy(), FlushBSS(_)).Times(0);
|
|
InitiateScanInDarkResume(freqs);
|
|
EXPECT_FALSE(manager()->suppress_autoconnect());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, TriggerPassiveScan_NoResults) {
|
|
ScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(3);
|
|
const WiFi::FreqSet freqs;
|
|
EXPECT_CALL(netlink_manager_,
|
|
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
|
|
TriggerScanMessage::kCommand),
|
|
_, _, _));
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("Scanning on specific channels")))
|
|
.Times(0);
|
|
TriggerPassiveScan(freqs);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, TriggerPassiveScan_HasResults) {
|
|
ScopedMockLog log;
|
|
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(3);
|
|
const WiFi::FreqSet freqs = {1};
|
|
EXPECT_CALL(netlink_manager_,
|
|
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
|
|
TriggerScanMessage::kCommand),
|
|
_, _, _));
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log, Log(_, _, HasSubstr("Scanning on specific channels")))
|
|
.Times(1);
|
|
TriggerPassiveScan(freqs);
|
|
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
|
|
ScopeLogger::GetInstance()->set_verbose_level(0);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, PendingScanEvents) {
|
|
// This test essentially performs ReportBSS(), but ensures that the
|
|
// WiFi object successfully dispatches events in order.
|
|
StartWiFi();
|
|
BSSAdded(
|
|
"bss0",
|
|
CreateBSSProperties("ssid0", "00:00:00:00:00:00", 0, 0,
|
|
kNetworkModeInfrastructure));
|
|
BSSAdded(
|
|
"bss1",
|
|
CreateBSSProperties("ssid1", "00:00:00:00:00:01", 0, 0,
|
|
kNetworkModeInfrastructure));
|
|
BSSRemoved("bss0");
|
|
BSSAdded(
|
|
"bss2",
|
|
CreateBSSProperties("ssid2", "00:00:00:00:00:02", 0, 0,
|
|
kNetworkModeInfrastructure));
|
|
|
|
WiFiEndpointRefPtr ap0 = MakeEndpoint("ssid0", "00:00:00:00:00:00");
|
|
WiFiEndpointRefPtr ap1 = MakeEndpoint("ssid1", "00:00:00:00:00:01");
|
|
WiFiEndpointRefPtr ap2 = MakeEndpoint("ssid2", "00:00:00:00:00:02");
|
|
|
|
InSequence seq;
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointAdded(EndpointMatch(ap0)));
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointAdded(EndpointMatch(ap1)));
|
|
WiFiServiceRefPtr null_service;
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointRemoved(EndpointMatch(ap0)))
|
|
.WillOnce(Return(null_service));
|
|
EXPECT_CALL(*wifi_provider(), OnEndpointAdded(EndpointMatch(ap2)));
|
|
dispatcher_.DispatchPendingEvents();
|
|
Mock::VerifyAndClearExpectations(wifi_provider());
|
|
|
|
const WiFi::EndpointMap& endpoints_by_rpcid = GetEndpointMap();
|
|
EXPECT_EQ(2, endpoints_by_rpcid.size());
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ParseWiphyIndex_Success) {
|
|
// Verify that the wiphy index in kNewWiphyNlMsg is parsed, and that the flag
|
|
// for having the wiphy index is set by ParseWiphyIndex.
|
|
EXPECT_EQ(GetWiphyIndex(), WiFi::kDefaultWiphyIndex);
|
|
NewWiphyMessage msg;
|
|
NetlinkPacket packet(kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg));
|
|
msg.InitFromPacket(&packet, NetlinkMessage::MessageContext());
|
|
EXPECT_TRUE(ParseWiphyIndex(msg));
|
|
EXPECT_EQ(GetWiphyIndex(), kNewWiphyNlMsg_WiphyIndex);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, ParseWiphyIndex_Failure) {
|
|
ScopedMockLog log;
|
|
// Change the NL80211_ATTR_WIPHY U32 attribute to the NL80211_ATTR_WIPHY_FREQ
|
|
// U32 attribute, so that this message no longer contains a wiphy_index to be
|
|
// parsed.
|
|
NewWiphyMessage msg;
|
|
MutableNetlinkPacket packet(kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg));
|
|
struct nlattr* nl80211_attr_wiphy = reinterpret_cast<struct nlattr*>(
|
|
&packet.GetMutablePayload()->GetData()[
|
|
kNewWiphyNlMsg_Nl80211AttrWiphyOffset]);
|
|
nl80211_attr_wiphy->nla_type = NL80211_ATTR_WIPHY_FREQ;
|
|
msg.InitFromPacket(&packet, NetlinkMessage::MessageContext());
|
|
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
|
|
EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
|
|
"NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY"));
|
|
EXPECT_FALSE(ParseWiphyIndex(msg));
|
|
EXPECT_CALL(*wake_on_wifi_, OnWiphyIndexReceived(_)).Times(0);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, OnScanStarted_ActiveScan) {
|
|
SetWiphyIndex(kScanTriggerMsgWiphyIndex);
|
|
TriggerScanMessage msg;
|
|
NetlinkPacket packet(
|
|
kActiveScanTriggerNlMsg, sizeof(kActiveScanTriggerNlMsg));
|
|
msg.InitFromPacket(&packet, NetlinkMessage::MessageContext());
|
|
EXPECT_CALL(*wake_on_wifi_, OnScanStarted(true));
|
|
OnScanStarted(msg);
|
|
}
|
|
|
|
TEST_F(WiFiMainTest, OnScanStarted_PassiveScan) {
|
|
SetWiphyIndex(kScanTriggerMsgWiphyIndex);
|
|
TriggerScanMessage msg;
|
|
NetlinkPacket packet(
|
|
kPassiveScanTriggerNlMsg, sizeof(kPassiveScanTriggerNlMsg));
|
|
msg.InitFromPacket(&packet, NetlinkMessage::MessageContext());
|
|
EXPECT_CALL(*wake_on_wifi_, OnScanStarted(false));
|
|
OnScanStarted(msg);
|
|
}
|
|
|
|
} // namespace shill
|