scan_utils_unittest.cpp revision 1aadd2c3781ee882e77dae2f4dc38fe3574fdca7
1/* 2 * Copyright (C) 2016, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <functional> 18#include <memory> 19#include <vector> 20 21#include <linux/netlink.h> 22#include <linux/nl80211.h> 23 24#include <gtest/gtest.h> 25 26#include "wificond/scanning/scan_result.h" 27#include "wificond/scanning/scan_utils.h" 28#include "wificond/tests/mock_netlink_manager.h" 29 30using std::bind; 31using std::placeholders::_1; 32using std::placeholders::_2; 33using std::unique_ptr; 34using std::vector; 35using testing::Invoke; 36using testing::NiceMock; 37using testing::Return; 38using testing::_; 39 40using com::android::server::wifi::wificond::NativeScanResult; 41 42namespace android { 43namespace wificond { 44 45namespace { 46 47constexpr uint32_t kFakeInterfaceIndex = 12; 48constexpr uint32_t kFakeScheduledScanIntervalMs = 20000; 49constexpr uint32_t kFakeSequenceNumber = 1984; 50constexpr int kFakeErrorCode = EIO; 51constexpr int32_t kFakeRssiThreshold = -80; 52constexpr bool kFakeUseRandomMAC = true; 53 54// Currently, control messages are only created by the kernel and sent to us. 55// Therefore NL80211Packet doesn't have corresponding constructor. 56// For test we manually create control messages using this helper function. 57NL80211Packet CreateControlMessageError(int error_code) { 58 vector<uint8_t> data; 59 data.resize(NLMSG_HDRLEN + NLA_ALIGN(sizeof(int)), 0); 60 // Initialize length field. 61 nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data.data()); 62 nl_header->nlmsg_len = data.size(); 63 nl_header->nlmsg_type = NLMSG_ERROR; 64 nl_header->nlmsg_seq = kFakeSequenceNumber; 65 nl_header->nlmsg_pid = getpid(); 66 int* error_field = reinterpret_cast<int*>(data.data() + NLMSG_HDRLEN); 67 *error_field = -error_code; 68 69 return NL80211Packet(data); 70} 71 72NL80211Packet CreateControlMessageAck() { 73 return CreateControlMessageError(0); 74} 75 76// This is a helper function to mock the behavior of NetlinkManager:: 77// SendMessageAndGetResponses() when we expect a single packet response. 78// |request_message| and |response| are mapped to existing parameters of 79// SendMessageAndGetResponses(). 80// |mock_response| and |mock_return value| are additional parameters used 81// for specifying expected results, 82bool AppendMessageAndReturn( 83 NL80211Packet& mock_response, 84 bool mock_return_value, 85 const NL80211Packet& request_message, 86 vector<std::unique_ptr<const NL80211Packet>>* response) { 87 response->push_back(std::make_unique<NL80211Packet>(mock_response)); 88 return mock_return_value; 89} 90 91} // namespace 92 93class ScanUtilsTest : public ::testing::Test { 94 protected: 95 virtual void SetUp() { 96 ON_CALL(netlink_manager_, 97 SendMessageAndGetResponses(_, _)).WillByDefault(Return(true)); 98 } 99 100 NiceMock<MockNetlinkManager> netlink_manager_; 101 ScanUtils scan_utils_{&netlink_manager_}; 102}; 103 104MATCHER_P(DoesNL80211PacketMatchCommand, command, 105 "Check if the netlink packet matches |command|") { 106 return arg.GetCommand() == command; 107} 108 109TEST_F(ScanUtilsTest, CanGetScanResult) { 110 vector<NativeScanResult> scan_results; 111 EXPECT_CALL( 112 netlink_manager_, 113 SendMessageAndGetResponses( 114 DoesNL80211PacketMatchCommand(NL80211_CMD_GET_SCAN), _)); 115 116 // We don't use EXPECT_TRUE here because we need to mock a complete 117 // response for NL80211_CMD_GET_SCAN to satisfy the parsing code called 118 // by GetScanResult. 119 // TODO(b/34231002): Mock response for NL80211_CMD_GET_SCAN. 120 // TODO(b/34231420): Add validation of interface index. 121 scan_utils_.GetScanResult(kFakeInterfaceIndex, &scan_results); 122} 123 124TEST_F(ScanUtilsTest, CanSendScanRequest) { 125 NL80211Packet response = CreateControlMessageAck(); 126 EXPECT_CALL( 127 netlink_manager_, 128 SendMessageAndGetResponses( 129 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)). 130 WillOnce(Invoke(bind( 131 AppendMessageAndReturn, response, true, _1, _2))); 132 133 int errno_ignored; 134 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC, {}, {}, 135 &errno_ignored)); 136 // TODO(b/34231420): Add validation of requested scan ssids, threshold, 137 // and frequencies. 138} 139 140TEST_F(ScanUtilsTest, CanHandleScanRequestFailure) { 141 NL80211Packet response = CreateControlMessageError(kFakeErrorCode); 142 EXPECT_CALL( 143 netlink_manager_, 144 SendMessageAndGetResponses( 145 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)). 146 WillOnce(Invoke(bind( 147 AppendMessageAndReturn, response, true, _1, _2))); 148 int error_code; 149 EXPECT_FALSE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC, {}, {}, 150 &error_code)); 151 EXPECT_EQ(kFakeErrorCode, error_code); 152} 153 154TEST_F(ScanUtilsTest, CanSendSchedScanRequest) { 155 NL80211Packet response = CreateControlMessageAck(); 156 EXPECT_CALL( 157 netlink_manager_, 158 SendMessageAndGetResponses( 159 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)). 160 WillOnce(Invoke(bind( 161 AppendMessageAndReturn, response, true, _1, _2))); 162 int errno_ignored; 163 EXPECT_TRUE(scan_utils_.StartScheduledScan( 164 kFakeInterfaceIndex, 165 kFakeScheduledScanIntervalMs, 166 kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored)); 167 // TODO(b/34231420): Add validation of requested scan ssids, threshold, 168 // and frequencies. 169} 170 171TEST_F(ScanUtilsTest, CanHandleSchedScanRequestFailure) { 172 NL80211Packet response = CreateControlMessageError(kFakeErrorCode); 173 EXPECT_CALL( 174 netlink_manager_, 175 SendMessageAndGetResponses( 176 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)). 177 WillOnce(Invoke(bind( 178 AppendMessageAndReturn, response, true, _1, _2))); 179 int error_code; 180 EXPECT_FALSE(scan_utils_.StartScheduledScan( 181 kFakeInterfaceIndex, 182 kFakeScheduledScanIntervalMs, 183 kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &error_code)); 184 EXPECT_EQ(kFakeErrorCode, error_code); 185} 186 187TEST_F(ScanUtilsTest, CanPrioritizeLastSeenSinceBootNetlinkAttribute) { 188 constexpr uint64_t kLastSeenTimestampNanoSeconds = 123456; 189 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321; 190 NL80211NestedAttr bss(NL80211_ATTR_BSS); 191 bss.AddAttribute( 192 NL80211Attr<uint64_t>(NL80211_BSS_LAST_SEEN_BOOTTIME, 193 kLastSeenTimestampNanoSeconds)); 194 bss.AddAttribute( 195 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds)); 196 uint64_t timestamp_microseconds; 197 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting( 198 bss, ×tamp_microseconds)); 199 EXPECT_EQ(kLastSeenTimestampNanoSeconds/1000, timestamp_microseconds); 200} 201 202TEST_F(ScanUtilsTest, CanHandleMissingLastSeenSinceBootNetlinkAttribute) { 203 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321; 204 NL80211NestedAttr bss(NL80211_ATTR_BSS); 205 bss.AddAttribute( 206 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds)); 207 uint64_t timestamp_microseconds; 208 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting( 209 bss, ×tamp_microseconds)); 210 EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds); 211} 212 213// Probe TSF is newer. 214TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon1) { 215 constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds = 654321; 216 constexpr uint64_t kBssTsfTimestampMicroSeconds = 217 kBssBeaconTsfTimestampMicroSeconds + 2000; 218 NL80211NestedAttr bss(NL80211_ATTR_BSS); 219 bss.AddAttribute( 220 NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF, 221 kBssBeaconTsfTimestampMicroSeconds)); 222 bss.AddAttribute( 223 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds)); 224 uint64_t timestamp_microseconds; 225 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting( 226 bss, ×tamp_microseconds)); 227 EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds); 228} 229 230// Beacon TSF is newer. 231TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon2) { 232 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321; 233 constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds = 234 kBssTsfTimestampMicroSeconds + 2000; 235 NL80211NestedAttr bss(NL80211_ATTR_BSS); 236 bss.AddAttribute( 237 NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF, 238 kBssBeaconTsfTimestampMicroSeconds)); 239 bss.AddAttribute( 240 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds)); 241 uint64_t timestamp_microseconds; 242 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting( 243 bss, ×tamp_microseconds)); 244 EXPECT_EQ(kBssBeaconTsfTimestampMicroSeconds, timestamp_microseconds); 245} 246 247} // namespace wificond 248} // namespace android 249