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