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, &timestamp_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, &timestamp_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, &timestamp_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, &timestamp_microseconds));
244  EXPECT_EQ(kBssBeaconTsfTimestampMicroSeconds, timestamp_microseconds);
245}
246
247}  // namespace wificond
248}  // namespace android
249