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