• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 using std::bind;
31 using std::placeholders::_1;
32 using std::placeholders::_2;
33 using std::unique_ptr;
34 using std::vector;
35 using testing::Invoke;
36 using testing::NiceMock;
37 using testing::Return;
38 using testing::_;
39 
40 using com::android::server::wifi::wificond::NativeScanResult;
41 
42 namespace android {
43 namespace wificond {
44 
45 namespace {
46 
47 constexpr uint32_t kFakeInterfaceIndex = 12;
48 constexpr uint32_t kFakeScheduledScanIntervalMs = 20000;
49 constexpr uint32_t kFakeSequenceNumber = 1984;
50 constexpr int kFakeErrorCode = EIO;
51 constexpr int32_t kFakeRssiThreshold = -80;
52 constexpr 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.
CreateControlMessageError(int error_code)57 NL80211Packet 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 
CreateControlMessageAck()72 NL80211Packet 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,
AppendMessageAndReturn(NL80211Packet & mock_response,bool mock_return_value,const NL80211Packet & request_message,vector<std::unique_ptr<const NL80211Packet>> * response)82 bool 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 
93 class ScanUtilsTest : public ::testing::Test {
94  protected:
SetUp()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 
104 MATCHER_P(DoesNL80211PacketMatchCommand, command,
105           "Check if the netlink packet matches |command|") {
106   return arg.GetCommand() == command;
107 }
108 
TEST_F(ScanUtilsTest,CanGetScanResult)109 TEST_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 
TEST_F(ScanUtilsTest,CanSendScanRequest)124 TEST_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 
TEST_F(ScanUtilsTest,CanHandleScanRequestFailure)138 TEST_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 
TEST_F(ScanUtilsTest,CanSendSchedScanRequest)149 TEST_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 
TEST_F(ScanUtilsTest,CanHandleSchedScanRequestFailure)165 TEST_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