You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
448 lines
19 KiB
448 lines
19 KiB
/* |
|
* Copyright (C) 2017, 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 <vector> |
|
|
|
#include <gmock/gmock.h> |
|
#include <gtest/gtest.h> |
|
#include <wifi_system_test/mock_interface_tool.h> |
|
#include <wifi_system_test/mock_supplicant_manager.h> |
|
|
|
#include "wificond/scanning/offload/offload_scan_utils.h" |
|
#include "wificond/scanning/scanner_impl.h" |
|
#include "wificond/tests/mock_client_interface_impl.h" |
|
#include "wificond/tests/mock_netlink_manager.h" |
|
#include "wificond/tests/mock_netlink_utils.h" |
|
#include "wificond/tests/mock_offload_scan_callback_interface_impl.h" |
|
#include "wificond/tests/mock_offload_scan_manager.h" |
|
#include "wificond/tests/mock_offload_service_utils.h" |
|
#include "wificond/tests/mock_scan_utils.h" |
|
#include "wificond/tests/offload_test_utils.h" |
|
|
|
using ::android::binder::Status; |
|
using ::android::wifi_system::MockInterfaceTool; |
|
using ::android::wifi_system::MockSupplicantManager; |
|
using ::com::android::server::wifi::wificond::SingleScanSettings; |
|
using ::com::android::server::wifi::wificond::PnoSettings; |
|
using ::com::android::server::wifi::wificond::NativeScanResult; |
|
using android::hardware::wifi::offload::V1_0::ScanResult; |
|
using ::testing::Invoke; |
|
using ::testing::NiceMock; |
|
using ::testing::Return; |
|
using ::testing::_; |
|
using std::shared_ptr; |
|
using std::unique_ptr; |
|
using std::vector; |
|
|
|
using namespace std::placeholders; |
|
|
|
namespace android { |
|
namespace wificond { |
|
|
|
namespace { |
|
|
|
constexpr uint32_t kFakeInterfaceIndex = 12; |
|
constexpr uint32_t kFakeWiphyIndex = 5; |
|
constexpr uint32_t kFakeScanIntervalMs = 10000; |
|
|
|
// This is a helper function to mock the behavior of ScanUtils::Scan() |
|
// when we expect a error code. |
|
// |interface_index_ignored|, |request_random_mac_ignored|, |ssids_ignored|, |
|
// |freqs_ignored|, |error_code| are mapped to existing parameters of ScanUtils::Scan(). |
|
// |mock_error_code| is a additional parameter used for specifying expected error code. |
|
bool ReturnErrorCodeForScanRequest( |
|
int mock_error_code, |
|
uint32_t interface_index_ignored, |
|
bool request_random_mac_ignored, |
|
const std::vector<std::vector<uint8_t>>& ssids_ignored, |
|
const std::vector<uint32_t>& freqs_ignored, |
|
int* error_code) { |
|
*error_code = mock_error_code; |
|
// Returing false because this helper function is used for failure case. |
|
return false; |
|
} |
|
|
|
bool CaptureSchedScanIntervalSetting( |
|
uint32_t /* interface_index */, |
|
const SchedScanIntervalSetting& interval_setting, |
|
int32_t /* rssi_threshold */, |
|
bool /* request_random_mac */, |
|
const std::vector<std::vector<uint8_t>>& /* scan_ssids */, |
|
const std::vector<std::vector<uint8_t>>& /* match_ssids */, |
|
const std::vector<uint32_t>& /* freqs */, |
|
int* /* error_code */, |
|
SchedScanIntervalSetting* out_interval_setting) { |
|
*out_interval_setting = interval_setting; |
|
return true; |
|
} |
|
|
|
bool ReturnOffloadScanResults( |
|
std::vector<NativeScanResult>* native_scan_results_, |
|
const std::vector<ScanResult>& offload_scan_results) { |
|
return OffloadScanUtils::convertToNativeScanResults(offload_scan_results, |
|
native_scan_results_); |
|
} |
|
|
|
bool ReturnNetlinkScanResults( |
|
uint32_t interface_index, |
|
std::vector<NativeScanResult>* native_scan_results_, |
|
const std::vector<ScanResult>& offload_scan_results) { |
|
return OffloadScanUtils::convertToNativeScanResults(offload_scan_results, |
|
native_scan_results_); |
|
} |
|
|
|
} // namespace |
|
|
|
class ScannerTest : public ::testing::Test { |
|
protected: |
|
void SetUp() override { |
|
ON_CALL(*offload_service_utils_, GetOffloadScanManager(_, _)) |
|
.WillByDefault(Return(offload_scan_manager_)); |
|
ON_CALL(*offload_service_utils_, GetOffloadScanCallbackInterface(_)) |
|
.WillByDefault(Return(offload_scan_callback_interface_)); |
|
dummy_scan_results_ = OffloadTestUtils::createOffloadScanResults(); |
|
} |
|
|
|
void TearDown() override { dummy_scan_results_.clear(); } |
|
|
|
unique_ptr<ScannerImpl> scanner_impl_; |
|
NiceMock<MockNetlinkManager> netlink_manager_; |
|
NiceMock<MockNetlinkUtils> netlink_utils_{&netlink_manager_}; |
|
NiceMock<MockScanUtils> scan_utils_{&netlink_manager_}; |
|
NiceMock<MockInterfaceTool> if_tool_; |
|
NiceMock<MockSupplicantManager> supplicant_manager_; |
|
NiceMock<MockClientInterfaceImpl> client_interface_impl_{ |
|
&if_tool_, &supplicant_manager_, &netlink_utils_, &scan_utils_}; |
|
shared_ptr<NiceMock<MockOffloadServiceUtils>> offload_service_utils_{ |
|
new NiceMock<MockOffloadServiceUtils>()}; |
|
shared_ptr<NiceMock<MockOffloadScanCallbackInterfaceImpl>> |
|
offload_scan_callback_interface_{ |
|
new NiceMock<MockOffloadScanCallbackInterfaceImpl>( |
|
scanner_impl_.get())}; |
|
std::shared_ptr<NiceMock<MockOffloadScanManager>> offload_scan_manager_{ |
|
new NiceMock<MockOffloadScanManager>(offload_service_utils_, |
|
offload_scan_callback_interface_)}; |
|
ScanCapabilities scan_capabilities_; |
|
WiphyFeatures wiphy_features_; |
|
std::vector<ScanResult> dummy_scan_results_; |
|
}; |
|
|
|
TEST_F(ScannerTest, TestSingleScan) { |
|
EXPECT_CALL(scan_utils_, Scan(_, _, _, _, _)).WillOnce(Return(true)); |
|
bool success = false; |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
EXPECT_TRUE(scanner_impl_->scan(SingleScanSettings(), &success).isOk()); |
|
EXPECT_TRUE(success); |
|
} |
|
|
|
TEST_F(ScannerTest, TestSingleScanFailure) { |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
EXPECT_CALL( |
|
scan_utils_, |
|
Scan(_, _, _, _, _)). |
|
WillOnce(Invoke(bind( |
|
ReturnErrorCodeForScanRequest, EBUSY, _1, _2, _3, _4, _5))); |
|
|
|
bool success = false; |
|
EXPECT_TRUE(scanner_impl_->scan(SingleScanSettings(), &success).isOk()); |
|
EXPECT_FALSE(success); |
|
} |
|
|
|
TEST_F(ScannerTest, TestProcessAbortsOnScanReturningNoDeviceError) { |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
ON_CALL( |
|
scan_utils_, |
|
Scan(_, _, _, _, _)). |
|
WillByDefault(Invoke(bind( |
|
ReturnErrorCodeForScanRequest, ENODEV, _1, _2, _3, _4, _5))); |
|
|
|
bool success_ignored; |
|
EXPECT_DEATH(scanner_impl_->scan(SingleScanSettings(), &success_ignored), |
|
"Driver is in a bad state*"); |
|
} |
|
|
|
TEST_F(ScannerTest, TestAbortScan) { |
|
bool single_scan_success = false; |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
EXPECT_CALL(scan_utils_, Scan(_, _, _, _, _)).WillOnce(Return(true)); |
|
EXPECT_TRUE( |
|
scanner_impl_->scan(SingleScanSettings(), &single_scan_success).isOk()); |
|
EXPECT_TRUE(single_scan_success); |
|
|
|
EXPECT_CALL(scan_utils_, AbortScan(_)); |
|
EXPECT_TRUE(scanner_impl_->abortScan().isOk()); |
|
} |
|
|
|
TEST_F(ScannerTest, TestAbortScanNotIssuedIfNoOngoingScan) { |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
EXPECT_CALL(scan_utils_, AbortScan(_)).Times(0); |
|
EXPECT_TRUE(scanner_impl_->abortScan().isOk()); |
|
} |
|
|
|
TEST_F(ScannerTest, TestGetScanResults) { |
|
vector<NativeScanResult> scan_results; |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
EXPECT_CALL(scan_utils_, GetScanResult(_, _)).WillOnce(Return(true)); |
|
EXPECT_TRUE(scanner_impl_->getScanResults(&scan_results).isOk()); |
|
} |
|
|
|
TEST_F(ScannerTest, TestStartPnoScanViaNetlink) { |
|
bool success = false; |
|
EXPECT_CALL(*offload_service_utils_, IsOffloadScanSupported()) |
|
.Times(1) |
|
.WillRepeatedly(Return(false)); |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
EXPECT_CALL(scan_utils_, StartScheduledScan(_, _, _, _, _, _, _, _)). |
|
WillOnce(Return(true)); |
|
EXPECT_TRUE(scanner_impl_->startPnoScan(PnoSettings(), &success).isOk()); |
|
EXPECT_TRUE(success); |
|
} |
|
|
|
TEST_F(ScannerTest, TestStopPnoScanViaNetlink) { |
|
bool success = false; |
|
EXPECT_CALL(*offload_service_utils_, IsOffloadScanSupported()) |
|
.Times(1) |
|
.WillRepeatedly(Return(false)); |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
// StopScheduledScan() will be called no matter if there is an ongoing |
|
// scheduled scan or not. This is for making the system more robust. |
|
EXPECT_CALL(scan_utils_, StopScheduledScan(_)).WillOnce(Return(true)); |
|
EXPECT_TRUE(scanner_impl_->stopPnoScan(&success).isOk()); |
|
EXPECT_TRUE(success); |
|
} |
|
|
|
TEST_F(ScannerTest, TestStartScanOverOffload) { |
|
bool success = false; |
|
EXPECT_CALL(*offload_service_utils_, IsOffloadScanSupported()) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
EXPECT_CALL(*offload_scan_manager_, startScan(_, _, _, _, _, _, _)) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
EXPECT_CALL(*offload_scan_manager_, stopScan(_)) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
scanner_impl_->startPnoScan(PnoSettings(), &success); |
|
EXPECT_TRUE(success); |
|
scanner_impl_->stopPnoScan(&success); |
|
EXPECT_TRUE(success); |
|
} |
|
|
|
TEST_F(ScannerTest, TestStartScanOverNetlinkFallback) { |
|
bool success = false; |
|
ON_CALL(*offload_service_utils_, IsOffloadScanSupported()) |
|
.WillByDefault(Return(true)); |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
EXPECT_CALL(*offload_scan_manager_, startScan(_, _, _, _, _, _, _)) |
|
.WillOnce(Return(false)); |
|
EXPECT_CALL(*offload_scan_manager_, stopScan(_)).Times(0); |
|
EXPECT_CALL(scan_utils_, StartScheduledScan(_, _, _, _, _, _, _, _)) |
|
.WillOnce(Return(true)); |
|
EXPECT_CALL(scan_utils_, StopScheduledScan(_)).WillOnce(Return(true)); |
|
EXPECT_TRUE(scanner_impl_->startPnoScan(PnoSettings(), &success).isOk()); |
|
EXPECT_TRUE(success == true); |
|
scanner_impl_->stopPnoScan(&success); |
|
EXPECT_TRUE(success); |
|
} |
|
|
|
TEST_F(ScannerTest, TestAsyncErrorOverOffload) { |
|
bool success = false; |
|
EXPECT_CALL(*offload_service_utils_, IsOffloadScanSupported()) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
EXPECT_CALL(*offload_scan_manager_, startScan(_, _, _, _, _, _, _)) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
EXPECT_CALL(*offload_scan_manager_, stopScan(_)) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
EXPECT_CALL(scan_utils_, StartScheduledScan(_, _, _, _, _, _, _, _)) |
|
.WillOnce(Return(true)); |
|
EXPECT_CALL(scan_utils_, StopScheduledScan(_)).WillOnce(Return(true)); |
|
scanner_impl_->startPnoScan(PnoSettings(), &success); |
|
EXPECT_TRUE(success); |
|
scanner_impl_->OnOffloadError( |
|
OffloadScanCallbackInterface::AsyncErrorReason::REMOTE_FAILURE); |
|
scanner_impl_->stopPnoScan(&success); |
|
EXPECT_TRUE(success); |
|
} |
|
|
|
TEST_F(ScannerTest, TestGetScanResultsFromOffload) { |
|
bool success = false; |
|
EXPECT_CALL(*offload_service_utils_, IsOffloadScanSupported()) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
EXPECT_CALL(*offload_scan_manager_, startScan(_, _, _, _, _, _, _)) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
EXPECT_CALL(*offload_scan_manager_, getScanResults(_)) |
|
.Times(1) |
|
.WillOnce( |
|
Invoke(bind(ReturnOffloadScanResults, _1, dummy_scan_results_))); |
|
EXPECT_CALL(*offload_scan_manager_, stopScan(_)) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
scanner_impl_->startPnoScan(PnoSettings(), &success); |
|
EXPECT_TRUE(success); |
|
scanner_impl_->OnOffloadScanResult(); |
|
std::vector<NativeScanResult> scan_results; |
|
EXPECT_TRUE(scanner_impl_->getPnoScanResults(&scan_results).isOk()); |
|
EXPECT_FALSE(scan_results.empty()); |
|
scanner_impl_->stopPnoScan(&success); |
|
EXPECT_TRUE(success); |
|
} |
|
|
|
TEST_F(ScannerTest, TestGetScanResultsWhenOffloadFails) { |
|
bool success = false; |
|
EXPECT_CALL(*offload_service_utils_, IsOffloadScanSupported()) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
EXPECT_CALL(*offload_scan_manager_, startScan(_, _, _, _, _, _, _)) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
EXPECT_CALL(*offload_scan_manager_, stopScan(_)) |
|
.Times(1) |
|
.WillRepeatedly(Return(true)); |
|
EXPECT_CALL(*offload_scan_manager_, getScanResults(_)).Times(0); |
|
EXPECT_CALL(scan_utils_, GetScanResult(_, _)) |
|
.Times(1) |
|
.WillOnce( |
|
Invoke(bind(ReturnNetlinkScanResults, _1, _2, dummy_scan_results_))); |
|
scanner_impl_.reset(new ScannerImpl(kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_, wiphy_features_, |
|
&client_interface_impl_, &netlink_utils_, |
|
&scan_utils_, offload_service_utils_)); |
|
EXPECT_CALL(scan_utils_, StartScheduledScan(_, _, _, _, _, _, _, _)) |
|
.WillOnce(Return(true)); |
|
EXPECT_CALL(scan_utils_, StopScheduledScan(_)).WillOnce(Return(true)); |
|
EXPECT_TRUE(scanner_impl_->startPnoScan(PnoSettings(), &success).isOk()); |
|
EXPECT_TRUE(success); |
|
scanner_impl_->OnOffloadError( |
|
OffloadScanCallbackInterface::AsyncErrorReason::REMOTE_FAILURE); |
|
std::vector<NativeScanResult> scan_results; |
|
EXPECT_TRUE(scanner_impl_->getPnoScanResults(&scan_results).isOk()); |
|
EXPECT_FALSE(scan_results.empty()); |
|
scanner_impl_->stopPnoScan(&success); |
|
EXPECT_TRUE(success); |
|
} |
|
|
|
TEST_F(ScannerTest, TestGenerateScanPlansIfDeviceSupports) { |
|
ScanCapabilities scan_capabilities_scan_plan_supported( |
|
0 /* max_num_scan_ssids */, |
|
0 /* max_num_sched_scan_ssids */, |
|
0 /* max_match_sets */, |
|
// Parameters above are not related to this test. |
|
2 /* 1 plan for finite repeated scan and 1 plan for ininfite scan loop */, |
|
kFakeScanIntervalMs * PnoSettings::kSlowScanIntervalMultiplier / 1000, |
|
PnoSettings::kFastScanIterations); |
|
ScannerImpl scanner( |
|
kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_scan_plan_supported, wiphy_features_, |
|
&client_interface_impl_, |
|
&netlink_utils_, &scan_utils_, offload_service_utils_); |
|
|
|
PnoSettings pno_settings; |
|
pno_settings.interval_ms_ = kFakeScanIntervalMs; |
|
|
|
SchedScanIntervalSetting interval_setting; |
|
EXPECT_CALL( |
|
scan_utils_, |
|
StartScheduledScan(_, _, _, _, _, _, _, _)). |
|
WillOnce(Invoke(bind( |
|
CaptureSchedScanIntervalSetting, |
|
_1, _2, _3, _4, _5, _6, _7, _8, &interval_setting))); |
|
|
|
bool success_ignored = 0; |
|
EXPECT_TRUE(scanner.startPnoScan(pno_settings, &success_ignored).isOk()); |
|
/* 1 plan for finite repeated scan */ |
|
EXPECT_EQ(1U, interval_setting.plans.size()); |
|
EXPECT_EQ(kFakeScanIntervalMs * PnoSettings::kSlowScanIntervalMultiplier, |
|
interval_setting.final_interval_ms); |
|
} |
|
|
|
TEST_F(ScannerTest, TestGenerateSingleIntervalIfDeviceDoesNotSupportScanPlan) { |
|
ScanCapabilities scan_capabilities_no_scan_plan_support( |
|
0 /* max_num_scan_ssids */, |
|
0 /* max_num_sched_scan_ssids */, |
|
0 /* max_match_sets */, |
|
// Parameters above are not related to this test. |
|
0 /* max_num_scan_plans */, |
|
0 /* max_scan_plan_interval */, |
|
0 /* max_scan_plan_iterations */); |
|
ScannerImpl scanner( |
|
kFakeWiphyIndex, kFakeInterfaceIndex, |
|
scan_capabilities_no_scan_plan_support, wiphy_features_, |
|
&client_interface_impl_, |
|
&netlink_utils_, &scan_utils_, offload_service_utils_); |
|
PnoSettings pno_settings; |
|
pno_settings.interval_ms_ = kFakeScanIntervalMs; |
|
|
|
SchedScanIntervalSetting interval_setting; |
|
EXPECT_CALL( |
|
scan_utils_, |
|
StartScheduledScan(_, _, _, _, _, _, _, _)). |
|
WillOnce(Invoke(bind( |
|
CaptureSchedScanIntervalSetting, |
|
_1, _2, _3, _4, _5, _6, _7, _8, &interval_setting))); |
|
|
|
bool success_ignored = 0; |
|
EXPECT_TRUE(scanner.startPnoScan(pno_settings, &success_ignored).isOk()); |
|
|
|
EXPECT_EQ(0U, interval_setting.plans.size()); |
|
EXPECT_EQ(kFakeScanIntervalMs, interval_setting.final_interval_ms); |
|
} |
|
|
|
} // namespace wificond |
|
} // namespace android
|
|
|