1//
2// Copyright (C) 2015 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 "shill/wifi/tdls_manager.h"
18
19#include <map>
20#include <string>
21
22#if defined(__ANDROID__)
23#include <dbus/service_constants.h>
24#else
25#include <chromeos/dbus/service_constants.h>
26#endif  // __ANDROID__
27#include <gmock/gmock.h>
28#include <gtest/gtest.h>
29
30#include "shill/error.h"
31#include "shill/mock_event_dispatcher.h"
32#include "shill/supplicant/mock_supplicant_interface_proxy.h"
33#include "shill/supplicant/wpa_supplicant.h"
34
35using std::string;
36using std::vector;
37using ::testing::_;
38using ::testing::Mock;
39using ::testing::Return;
40using ::testing::SetArgumentPointee;
41using ::testing::StrEq;
42using ::testing::StrictMock;
43
44namespace shill {
45
46class TDLSManagerTest : public testing::Test {
47 public:
48  TDLSManagerTest()
49      : tdls_manager_(&event_dispatcher_, &supplicant_interface_proxy_, "") {}
50
51  void SetPeerDiscovering(const string& peer_mac_address) {
52    tdls_manager_.peer_discovery_state_[peer_mac_address] =
53        TDLSManager::PeerDiscoveryState::kRequestSent;
54  }
55  bool IsPeerDiscovering(const string& peer_mac_address) {
56    return tdls_manager_.CheckDiscoveryState(peer_mac_address) ==
57        TDLSManager::PeerDiscoveryState::kRequestSent;
58  }
59
60  void SetPeerDiscovered(const string& peer_mac_address) {
61    tdls_manager_.peer_discovery_state_[peer_mac_address] =
62        TDLSManager::PeerDiscoveryState::kResponseReceived;
63  }
64  bool IsPeerDiscovered(const string& peer_mac_address) {
65    return tdls_manager_.CheckDiscoveryState(peer_mac_address) ==
66        TDLSManager::PeerDiscoveryState::kResponseReceived;
67  }
68
69  bool IsPeerDiscoveryCleanupTimerSetup() {
70    return !tdls_manager_.peer_discovery_cleanup_callback_.IsCancelled();
71  }
72
73  void OnPeerDiscoveryCleanup() {
74    return tdls_manager_.PeerDiscoveryCleanup();
75  }
76
77 protected:
78  StrictMock<MockEventDispatcher> event_dispatcher_;
79  StrictMock<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
80  TDLSManager tdls_manager_;
81};
82
83TEST_F(TDLSManagerTest, DiscoverPeer) {
84  const char kPeer[] = "peer";
85  Error error;
86
87  EXPECT_FALSE(IsPeerDiscovering(kPeer));
88  EXPECT_FALSE(IsPeerDiscoveryCleanupTimerSetup());
89
90  // TDLS discover operation succeed.
91  EXPECT_CALL(supplicant_interface_proxy_, TDLSDiscover(StrEq(kPeer)))
92      .WillOnce(Return(true));
93  // Post delayed task for discover peer cleanup timer.
94  EXPECT_CALL(event_dispatcher_, PostDelayedTask(_, _)).Times(1);
95  EXPECT_EQ("",
96            tdls_manager_.PerformOperation(
97                kPeer, kTDLSDiscoverOperation, &error));
98  EXPECT_TRUE(error.IsSuccess());
99  EXPECT_TRUE(IsPeerDiscovering(kPeer));
100  EXPECT_TRUE(IsPeerDiscoveryCleanupTimerSetup());
101  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
102  Mock::VerifyAndClearExpectations(&event_dispatcher_);
103
104  // TDLS discover operation failed.
105  error.Reset();
106  EXPECT_CALL(supplicant_interface_proxy_, TDLSDiscover(StrEq(kPeer)))
107      .WillOnce(Return(false));
108  EXPECT_CALL(event_dispatcher_, PostDelayedTask(_, _)).Times(0);
109  EXPECT_EQ("",
110            tdls_manager_.PerformOperation(
111                kPeer, kTDLSDiscoverOperation, &error));
112  EXPECT_EQ(Error::kOperationFailed, error.type());
113  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
114  Mock::VerifyAndClearExpectations(&event_dispatcher_);
115}
116
117TEST_F(TDLSManagerTest, SetupPeer) {
118  const char kPeer[] = "peer";
119  Error error;
120
121  // TDLS setup operation succeed.
122  EXPECT_CALL(supplicant_interface_proxy_, TDLSSetup(StrEq(kPeer)))
123      .WillOnce(Return(true));
124  EXPECT_EQ("",
125            tdls_manager_.PerformOperation(
126                kPeer, kTDLSSetupOperation, &error));
127  EXPECT_TRUE(error.IsSuccess());
128  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
129
130  // TDLS setup operation failed.
131  error.Reset();
132  EXPECT_CALL(supplicant_interface_proxy_, TDLSSetup(StrEq(kPeer)))
133      .WillOnce(Return(false));
134  EXPECT_EQ("",
135            tdls_manager_.PerformOperation(
136                kPeer, kTDLSSetupOperation, &error));
137  EXPECT_EQ(Error::kOperationFailed, error.type());
138  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
139}
140
141TEST_F(TDLSManagerTest, TeardownPeer) {
142  const char kPeer[] = "peer";
143  Error error;
144
145  // TDLS teardown operation succeed.
146  EXPECT_CALL(supplicant_interface_proxy_, TDLSTeardown(StrEq(kPeer)))
147      .WillOnce(Return(true));
148  EXPECT_EQ("",
149            tdls_manager_.PerformOperation(
150                kPeer, kTDLSTeardownOperation, &error));
151  EXPECT_TRUE(error.IsSuccess());
152  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
153
154  // TDLS teardown operation failed.
155  error.Reset();
156  EXPECT_CALL(supplicant_interface_proxy_, TDLSTeardown(StrEq(kPeer)))
157      .WillOnce(Return(false));
158  EXPECT_EQ("",
159            tdls_manager_.PerformOperation(
160                kPeer, kTDLSTeardownOperation, &error));
161  EXPECT_EQ(Error::kOperationFailed, error.type());
162  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
163}
164
165TEST_F(TDLSManagerTest, PeerStatus) {
166  const char kPeer[] = "peer";
167  Error error;
168
169  // TDLS status operation succeed.
170  const std::map<string, string> kTDLSStatusMap {
171    { "Baby, I don't care", kTDLSUnknownState },
172    { WPASupplicant::kTDLSStateConnected, kTDLSConnectedState },
173    { WPASupplicant::kTDLSStateDisabled, kTDLSDisabledState },
174    { WPASupplicant::kTDLSStatePeerDoesNotExist, kTDLSNonexistentState },
175    { WPASupplicant::kTDLSStatePeerNotConnected, kTDLSDisconnectedState },
176  };
177  for (const auto& it : kTDLSStatusMap) {
178    error.Reset();
179    EXPECT_CALL(supplicant_interface_proxy_, TDLSStatus(StrEq(kPeer), _))
180        .WillOnce(DoAll(SetArgumentPointee<1>(it.first), Return(true)));
181    EXPECT_EQ(it.second,
182              tdls_manager_.PerformOperation(
183                  kPeer, kTDLSStatusOperation, &error));
184    EXPECT_TRUE(error.IsSuccess());
185    Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
186  }
187
188  // Discovered Peer in non-existent state should return "Disconnected" state.
189  error.Reset();
190  SetPeerDiscovered(kPeer);
191  EXPECT_CALL(supplicant_interface_proxy_, TDLSStatus(StrEq(kPeer), _))
192      .WillOnce(
193          DoAll(SetArgumentPointee<1>(
194                    string(WPASupplicant::kTDLSStatePeerDoesNotExist)),
195                Return(true)));
196  EXPECT_EQ(kTDLSDisconnectedState,
197            tdls_manager_.PerformOperation(
198                kPeer, kTDLSStatusOperation, &error));
199  EXPECT_TRUE(error.IsSuccess());
200  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
201
202  // TDLS status operation failed.
203  error.Reset();
204  EXPECT_CALL(supplicant_interface_proxy_, TDLSStatus(StrEq(kPeer), _))
205      .WillOnce(Return(false));
206  EXPECT_EQ("",
207            tdls_manager_.PerformOperation(
208                kPeer, kTDLSStatusOperation, &error));
209  EXPECT_EQ(Error::kOperationFailed, error.type());
210  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
211}
212
213TEST_F(TDLSManagerTest, OnDiscoverResponseReceived) {
214  const char kPeer[] = "peer";
215
216  // Received discover response for a peer without discover request.
217  EXPECT_FALSE(IsPeerDiscovering(kPeer));
218  EXPECT_FALSE(IsPeerDiscovered(kPeer));
219  tdls_manager_.OnDiscoverResponseReceived(kPeer);
220  EXPECT_FALSE(IsPeerDiscovering(kPeer));
221  EXPECT_FALSE(IsPeerDiscovered(kPeer));
222
223  // Receive discover response for a peer with discover request.
224  SetPeerDiscovering(kPeer);
225  EXPECT_TRUE(IsPeerDiscovering(kPeer));
226  tdls_manager_.OnDiscoverResponseReceived(kPeer);
227  EXPECT_TRUE(IsPeerDiscovered(kPeer));
228}
229
230TEST_F(TDLSManagerTest, PeerDiscoveryCleanup) {
231  const char kPeer[] = "peer";
232
233  // Start TDLS discover for a peer |kPeer|.
234  Error error;
235  EXPECT_CALL(supplicant_interface_proxy_, TDLSDiscover(StrEq(kPeer)))
236      .WillOnce(Return(true));
237  // Post delayed task for discover peer cleanup timer.
238  EXPECT_CALL(event_dispatcher_, PostDelayedTask(_, _)).Times(1);
239  EXPECT_EQ("",
240            tdls_manager_.PerformOperation(
241                kPeer, kTDLSDiscoverOperation, &error));
242  EXPECT_TRUE(error.IsSuccess());
243  EXPECT_TRUE(IsPeerDiscovering(kPeer));
244  EXPECT_TRUE(IsPeerDiscoveryCleanupTimerSetup());
245  Mock::VerifyAndClearExpectations(&supplicant_interface_proxy_);
246  Mock::VerifyAndClearExpectations(&event_dispatcher_);
247
248  // Peer discovery cleanup.
249  OnPeerDiscoveryCleanup();
250  EXPECT_FALSE(IsPeerDiscovering(kPeer));
251}
252
253}  // namespace shill
254