• 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 <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