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 <array>
18 #include <memory>
19 #include <vector>
20
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <wifi_system_test/mock_interface_tool.h>
24
25 #include "wificond/client_interface_impl.h"
26 #include "wificond/tests/mock_i_send_mgmt_frame_event.h"
27 #include "wificond/tests/mock_netlink_manager.h"
28 #include "wificond/tests/mock_netlink_utils.h"
29 #include "wificond/tests/mock_scan_utils.h"
30
31 using android::wifi_system::MockInterfaceTool;
32 using std::unique_ptr;
33 using std::vector;
34 using testing::Mock;
35 using testing::NiceMock;
36 using testing::Return;
37 using testing::StrictMock;
38 using testing::_;
39
40 namespace android {
41 namespace wificond {
42 namespace {
43
44 const uint32_t kTestWiphyIndex = 2;
45 const char kTestInterfaceName[] = "testwifi0";
46 const uint32_t kTestInterfaceIndex = 42;
47 const uint64_t kCookie = 42;
48 const int32_t kAutoMcs = -1;
49 const int32_t kMcs = 5;
50 const uint8_t kTestFrame[] = {0x00, 0x01, 0x02, 0x03};
51
52 class ClientInterfaceImplTest : public ::testing::Test {
53 protected:
54
SetUp()55 void SetUp() override {
56 SetUp(WiphyFeatures());
57 }
58
59 /**
60 * call SetUp(WiphyFeatures wiphy_features) in your test function if
61 * you would like to change WiphyFeatures.
62 */
SetUp(WiphyFeatures wiphy_features)63 void SetUp(WiphyFeatures wiphy_features) {
64 EXPECT_CALL(*netlink_utils_,
65 SubscribeMlmeEvent(kTestInterfaceIndex, _));
66 EXPECT_CALL(*netlink_utils_,
67 GetWiphyInfo(kTestWiphyIndex, _, _, _))
68 .WillOnce([wiphy_features](uint32_t wiphy_index, BandInfo* out_band_info,
69 ScanCapabilities* out_scan_capabilities,
70 WiphyFeatures* out_wiphy_features) {
71 *out_wiphy_features = wiphy_features;
72 return true;
73 });
74 EXPECT_CALL(*netlink_utils_,
75 SubscribeFrameTxStatusEvent(kTestInterfaceIndex, _))
76 .WillOnce([this](uint32_t interface_index,
77 OnFrameTxStatusEventHandler handler) {
78 frame_tx_status_event_handler_ = handler;
79 });
80 EXPECT_CALL(*netlink_utils_,
81 SubscribeChannelSwitchEvent(kTestInterfaceIndex, _));
82 client_interface_.reset(new ClientInterfaceImpl{
83 kTestWiphyIndex,
84 kTestInterfaceName,
85 kTestInterfaceIndex,
86 std::array<uint8_t, ETH_ALEN>{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
87 if_tool_.get(),
88 netlink_utils_.get(),
89 scan_utils_.get()});
90 }
91
TearDown()92 void TearDown() override {
93 EXPECT_CALL(*netlink_utils_,
94 UnsubscribeMlmeEvent(kTestInterfaceIndex));
95 EXPECT_CALL(*netlink_utils_,
96 UnsubscribeFrameTxStatusEvent(kTestInterfaceIndex));
97 EXPECT_CALL(*netlink_utils_,
98 UnsubscribeChannelSwitchEvent(kTestInterfaceIndex));
99 }
100
101 unique_ptr<NiceMock<MockInterfaceTool>> if_tool_{
102 new NiceMock<MockInterfaceTool>};
103 unique_ptr<NiceMock<MockNetlinkManager>> netlink_manager_{
104 new NiceMock<MockNetlinkManager>()};
105 unique_ptr<NiceMock<MockNetlinkUtils>> netlink_utils_{
106 new NiceMock<MockNetlinkUtils>(netlink_manager_.get())};
107 unique_ptr<NiceMock<MockScanUtils>> scan_utils_{
108 new NiceMock<MockScanUtils>(netlink_manager_.get())};
109 unique_ptr<ClientInterfaceImpl> client_interface_;
110 OnFrameTxStatusEventHandler frame_tx_status_event_handler_;
111 sp<StrictMock<MockISendMgmtFrameEvent>> send_mgmt_frame_event_{
112 new StrictMock<MockISendMgmtFrameEvent>()};
113 }; // class ClientInterfaceImplTest
114
115 } // namespace
116
117 /**
118 * If the device does not support sending mgmt frame at specified MCS rate,
119 * and the caller specifies a MCS < 0, the call should still succeed (and the
120 * driver will determine the MCS rate automatically).
121 */
TEST_F(ClientInterfaceImplTest,SendMgmtFrameMcsUnsupportedAutoSelectMcs)122 TEST_F(ClientInterfaceImplTest, SendMgmtFrameMcsUnsupportedAutoSelectMcs) {
123 EXPECT_CALL(*netlink_utils_,
124 SendMgmtFrame(kTestInterfaceIndex,
125 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
126 kAutoMcs, _))
127 .WillOnce([](uint32_t interface_index, const vector<uint8_t>& frame,
128 int32_t mcs, uint64_t* out_cookie) {
129 *out_cookie = kCookie;
130 return true;
131 });
132
133 EXPECT_CALL(*send_mgmt_frame_event_, OnAck(_));
134
135 client_interface_->SendMgmtFrame(
136 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
137 send_mgmt_frame_event_, kAutoMcs);
138 frame_tx_status_event_handler_(kCookie, true);
139 }
140
141 /**
142 * If the device does not support sending mgmt frame at specified MCS rate,
143 * and the caller specifies a MCS >= 0, the call should fail.
144 */
TEST_F(ClientInterfaceImplTest,SendMgmtFrameMcsUnsupportedCallerSpecifiedMcs)145 TEST_F(ClientInterfaceImplTest, SendMgmtFrameMcsUnsupportedCallerSpecifiedMcs) {
146 EXPECT_CALL(*send_mgmt_frame_event_,
147 OnFailure(send_mgmt_frame_event_->SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED));
148
149 client_interface_->SendMgmtFrame(
150 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
151 send_mgmt_frame_event_, kMcs);
152 }
153
154 /**
155 * If the device does support sending mgmt frame at specified MCS rate and the
156 * user specifies a valid MCS rate, the call should succeed.
157 */
TEST_F(ClientInterfaceImplTest,SendMgmtFrameMcsSupported)158 TEST_F(ClientInterfaceImplTest, SendMgmtFrameMcsSupported) {
159 WiphyFeatures wiphy_features;
160 wiphy_features.supports_tx_mgmt_frame_mcs = true;
161 SetUp(wiphy_features);
162
163 EXPECT_CALL(*netlink_utils_,
164 SendMgmtFrame(kTestInterfaceIndex,
165 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
166 kMcs, _))
167 .WillOnce([](uint32_t interface_index, const vector<uint8_t>& frame,
168 int32_t mcs, uint64_t* out_cookie) {
169 *out_cookie = kCookie;
170 return true;
171 });
172
173 EXPECT_CALL(*send_mgmt_frame_event_, OnAck(_));
174
175 client_interface_->SendMgmtFrame(
176 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
177 send_mgmt_frame_event_, kMcs);
178 frame_tx_status_event_handler_(kCookie, true);
179 }
180
181 /**
182 * Transmitted frame was not ACKed.
183 */
TEST_F(ClientInterfaceImplTest,SendMgmtFrameNotAcked)184 TEST_F(ClientInterfaceImplTest, SendMgmtFrameNotAcked) {
185 EXPECT_CALL(*netlink_utils_,
186 SendMgmtFrame(kTestInterfaceIndex,
187 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
188 kAutoMcs, _))
189 .WillOnce([](uint32_t interface_index, const vector<uint8_t>& frame,
190 int32_t mcs, uint64_t* out_cookie) {
191 *out_cookie = kCookie;
192 return true;
193 });
194
195 EXPECT_CALL(*send_mgmt_frame_event_,
196 OnFailure(send_mgmt_frame_event_->SEND_MGMT_FRAME_ERROR_NO_ACK));
197
198 client_interface_->SendMgmtFrame(
199 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
200 send_mgmt_frame_event_, kAutoMcs);
201 frame_tx_status_event_handler_(kCookie, false);
202 }
203
204 /**
205 * Transmission failed due to unknown NL80211 error.
206 */
TEST_F(ClientInterfaceImplTest,SendMgmtFrameUnknownError)207 TEST_F(ClientInterfaceImplTest, SendMgmtFrameUnknownError) {
208 EXPECT_CALL(*netlink_utils_,
209 SendMgmtFrame(kTestInterfaceIndex,
210 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)), kAutoMcs, _))
211 .WillOnce([](uint32_t interface_index, const vector<uint8_t>& frame,
212 int32_t mcs, uint64_t* out_cookie) {
213 return false;
214 });
215
216 EXPECT_CALL(*send_mgmt_frame_event_,
217 OnFailure(send_mgmt_frame_event_->SEND_MGMT_FRAME_ERROR_UNKNOWN));
218
219 client_interface_->SendMgmtFrame(
220 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
221 send_mgmt_frame_event_, kAutoMcs);
222 }
223
224 /**
225 * Received cookie was different than expected; No callback should be triggered.
226 */
TEST_F(ClientInterfaceImplTest,SendMgmtFrameWrongCookie)227 TEST_F(ClientInterfaceImplTest, SendMgmtFrameWrongCookie) {
228 EXPECT_CALL(*netlink_utils_,
229 SendMgmtFrame(kTestInterfaceIndex,
230 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
231 kAutoMcs, _))
232 .WillOnce([](uint32_t interface_index, const vector<uint8_t>& frame,
233 int32_t mcs, uint64_t* out_cookie) {
234 *out_cookie = kCookie;
235 return true;
236 });
237
238 client_interface_->SendMgmtFrame(
239 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
240 send_mgmt_frame_event_, kAutoMcs);
241 frame_tx_status_event_handler_(
242 kCookie + 1, // wrong cookie
243 false);
244
245 // StrictMock<MockISendMgmtFrameEvent> will fail if any unexpected method is
246 // called, guaranteeing no interaction with the callback.
247 }
248
249 /**
250 * frame_tx_status_event_handler_ triggered even though no transmission is in
251 * progress. No callback should be triggered.
252 */
TEST_F(ClientInterfaceImplTest,SendMgmtFrameNoTxCallbackTriggered)253 TEST_F(ClientInterfaceImplTest, SendMgmtFrameNoTxCallbackTriggered) {
254 EXPECT_CALL(*netlink_utils_,
255 SendMgmtFrame(kTestInterfaceIndex,
256 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
257 kAutoMcs, _))
258 .WillOnce([](uint32_t interface_index, const vector<uint8_t>& frame,
259 int32_t mcs, uint64_t* out_cookie) {
260 *out_cookie = kCookie;
261 return true;
262 });
263
264 EXPECT_CALL(*send_mgmt_frame_event_,
265 OnFailure(send_mgmt_frame_event_->SEND_MGMT_FRAME_ERROR_NO_ACK));
266
267 client_interface_->SendMgmtFrame(
268 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
269 send_mgmt_frame_event_, kAutoMcs);
270 frame_tx_status_event_handler_(kCookie, false);
271
272 // transmission has finished here.
273
274 // Now send another Tx status event.
275 frame_tx_status_event_handler_(kCookie + 1, false);
276 // StrictMock<MockISendMgmtFrameEvent> will fail if any unexpected method is
277 // called, guaranteeing no more interaction with the callback.
278 }
279
280 /**
281 * Second transmission was started even though no Tx Status event was received
282 * for the first transmission. Should discard first transmission, and second
283 * transmission should work normally.
284 *
285 * Since timeout of this SendMgmtFrame() is managed by framework, and framework
286 * does not notify wificond when the call times out, wificond should still work
287 * when a second call is made, even though it seems as though the first call is
288 * still incomplete.
289 */
TEST_F(ClientInterfaceImplTest,SendMgmtFrameSecondTxWhileFirstTxIncomplete)290 TEST_F(ClientInterfaceImplTest, SendMgmtFrameSecondTxWhileFirstTxIncomplete) {
291 EXPECT_CALL(*netlink_utils_,
292 SendMgmtFrame(kTestInterfaceIndex,
293 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
294 kAutoMcs, _))
295 .WillOnce([](uint32_t interface_index, const vector<uint8_t>& frame,
296 int32_t mcs, uint64_t* out_cookie) {
297 *out_cookie = kCookie;
298 return true;
299 })
300 .WillOnce([](uint32_t interface_index, const vector<uint8_t>& frame,
301 int32_t mcs, uint64_t* out_cookie) {
302 *out_cookie = kCookie + 1;
303 return true;
304 });
305
306 // first transmission; no tx status
307 client_interface_->SendMgmtFrame(
308 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
309 send_mgmt_frame_event_, kAutoMcs);
310
311 sp<StrictMock<MockISendMgmtFrameEvent>> send_mgmt_frame_event2{
312 new StrictMock<MockISendMgmtFrameEvent>()};
313
314 EXPECT_CALL(*send_mgmt_frame_event2,
315 OnFailure(send_mgmt_frame_event_->SEND_MGMT_FRAME_ERROR_NO_ACK));
316
317 // second transmission; yes tx status
318 client_interface_->SendMgmtFrame(
319 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
320 send_mgmt_frame_event2, kAutoMcs);
321 frame_tx_status_event_handler_(kCookie + 1, false);
322
323 // now trigger tx status for first call; nothing should happen (implicitly
324 // verified by StrictMock).
325 frame_tx_status_event_handler_(kCookie, false);
326 }
327
328 /**
329 * Tests that internal state is reset correctly between calls by performing
330 * two transmissions in sequence.
331 */
TEST_F(ClientInterfaceImplTest,SendMgmtFrameInternalStateResetBetweenCalls)332 TEST_F(ClientInterfaceImplTest, SendMgmtFrameInternalStateResetBetweenCalls) {
333 EXPECT_CALL(*netlink_utils_,
334 SendMgmtFrame(kTestInterfaceIndex,
335 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
336 kAutoMcs, _))
337 .WillOnce([](uint32_t interface_index, const vector<uint8_t>& frame,
338 int32_t mcs, uint64_t* out_cookie) {
339 *out_cookie = kCookie;
340 return true;
341 });
342
343 EXPECT_CALL(*send_mgmt_frame_event_, OnAck(_));
344
345 client_interface_->SendMgmtFrame(
346 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
347 send_mgmt_frame_event_, kAutoMcs);
348 frame_tx_status_event_handler_(kCookie, true);
349
350 Mock::VerifyAndClearExpectations(netlink_utils_.get());
351 Mock::VerifyAndClearExpectations(send_mgmt_frame_event_.get());
352
353 uint64_t new_cookie = kCookie + 1;
354
355 EXPECT_CALL(*netlink_utils_,
356 SendMgmtFrame(kTestInterfaceIndex,
357 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
358 kAutoMcs, _))
359 .WillOnce([new_cookie](uint32_t interface_index,
360 const vector<uint8_t>& frame, int32_t mcs, uint64_t* out_cookie) {
361 *out_cookie = new_cookie;
362 return true;
363 });
364
365 EXPECT_CALL(*send_mgmt_frame_event_,
366 OnFailure(send_mgmt_frame_event_->SEND_MGMT_FRAME_ERROR_NO_ACK));
367
368 client_interface_->SendMgmtFrame(
369 vector<uint8_t>(std::begin(kTestFrame), std::end(kTestFrame)),
370 send_mgmt_frame_event_, kAutoMcs);
371 frame_tx_status_event_handler_(new_cookie, false);
372 }
373
374 } // namespace wificond
375 } // namespace android
376