scan_utils_unittest.cpp revision 8f62fdd7479506aa865560941d74dc4e4c77e1b3
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  EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC, {}, {}));
134  // TODO(b/34231420): Add validation of requested scan ssids, threshold,
135  // and frequencies.
136}
137
138TEST_F(ScanUtilsTest, CanHandleScanRequestFailure) {
139  NL80211Packet response = CreateControlMessageError(kFakeErrorCode);
140  EXPECT_CALL(
141      netlink_manager_,
142      SendMessageAndGetResponses(
143          DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)).
144              WillOnce(Invoke(bind(
145                  AppendMessageAndReturn, response, true, _1, _2)));
146  EXPECT_FALSE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC, {}, {}));
147}
148
149TEST_F(ScanUtilsTest, CanSendSchedScanRequest) {
150  NL80211Packet response = CreateControlMessageAck();
151  EXPECT_CALL(
152      netlink_manager_,
153       SendMessageAndGetResponses(
154           DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)).
155              WillOnce(Invoke(bind(
156                  AppendMessageAndReturn, response, true, _1, _2)));
157  EXPECT_TRUE(scan_utils_.StartScheduledScan(
158      kFakeInterfaceIndex,
159      kFakeScheduledScanIntervalMs,
160      kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}));
161  // TODO(b/34231420): Add validation of requested scan ssids, threshold,
162  // and frequencies.
163}
164
165TEST_F(ScanUtilsTest, CanHandleSchedScanRequestFailure) {
166  NL80211Packet response = CreateControlMessageError(kFakeErrorCode);
167  EXPECT_CALL(
168      netlink_manager_,
169       SendMessageAndGetResponses(
170           DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)).
171              WillOnce(Invoke(bind(
172                  AppendMessageAndReturn, response, true, _1, _2)));
173  EXPECT_FALSE(scan_utils_.StartScheduledScan(
174      kFakeInterfaceIndex,
175      kFakeScheduledScanIntervalMs,
176      kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}));
177}
178
179}  // namespace wificond
180}  // namespace android
181