blob: b3872b07713753d00f86a7ae9221222c18780447 [file] [log] [blame]
Chris Masone853b81b2011-06-24 14:11:41 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/wifi.h"
6
7#include <map>
8#include <string>
9#include <vector>
10
mukesh agrawaldc42bb32011-07-28 10:40:26 -070011#include <base/memory/scoped_ptr.h>
mukesh agrawal31950242011-07-14 11:53:38 -070012#include <base/string_number_conversions.h>
13#include <base/string_util.h>
Chris Masone853b81b2011-06-24 14:11:41 -070014#include <dbus-c++/dbus.h>
15#include <chromeos/dbus/service_constants.h>
Chris Masone7156c922011-08-23 20:36:21 -070016#include <gmock/gmock.h>
Chris Masone2ae797d2011-08-23 20:41:00 -070017#include <gtest/gtest.h>
Chris Masone853b81b2011-06-24 14:11:41 -070018
19#include "shill/dbus_adaptor.h"
20#include "shill/manager.h"
Chris Masone853b81b2011-06-24 14:11:41 -070021#include "shill/mock_device.h"
Chris Masone2ae797d2011-08-23 20:41:00 -070022#include "shill/mock_manager.h"
mukesh agrawal31950242011-07-14 11:53:38 -070023#include "shill/mock_supplicant_interface_proxy.h"
24#include "shill/mock_supplicant_process_proxy.h"
mukesh agrawaldc42bb32011-07-28 10:40:26 -070025#include "shill/nice_mock_control.h"
Chris Masone853b81b2011-06-24 14:11:41 -070026#include "shill/property_store_unittest.h"
mukesh agrawal31950242011-07-14 11:53:38 -070027#include "shill/proxy_factory.h"
28#include "shill/wifi_endpoint.h"
29#include "shill/wifi.h"
Chris Masone853b81b2011-06-24 14:11:41 -070030
31using std::map;
32using std::string;
33using std::vector;
34using ::testing::_;
mukesh agrawal31950242011-07-14 11:53:38 -070035using ::testing::AnyNumber;
36using ::testing::DefaultValue;
37using ::testing::InSequence;
mukesh agrawaldc42bb32011-07-28 10:40:26 -070038using ::testing::NiceMock;
Chris Masone853b81b2011-06-24 14:11:41 -070039using ::testing::Return;
40using ::testing::Test;
mukesh agrawal31950242011-07-14 11:53:38 -070041using ::testing::Throw;
Chris Masone853b81b2011-06-24 14:11:41 -070042
43namespace shill {
44
mukesh agrawal31950242011-07-14 11:53:38 -070045class WiFiPropertyTest : public PropertyStoreTest {
Chris Masone853b81b2011-06-24 14:11:41 -070046 public:
mukesh agrawal31950242011-07-14 11:53:38 -070047 WiFiPropertyTest()
Chris Masone626719f2011-08-18 16:58:48 -070048 : device_(new WiFi(&control_interface_, NULL, NULL, "wifi", "", 0)) {
Chris Masone853b81b2011-06-24 14:11:41 -070049 }
mukesh agrawal31950242011-07-14 11:53:38 -070050 virtual ~WiFiPropertyTest() {}
Chris Masone853b81b2011-06-24 14:11:41 -070051
52 protected:
53 DeviceRefPtr device_;
54};
55
mukesh agrawal31950242011-07-14 11:53:38 -070056TEST_F(WiFiPropertyTest, Contains) {
Chris Masone27c4aa52011-07-02 13:10:14 -070057 EXPECT_TRUE(device_->store()->Contains(flimflam::kNameProperty));
58 EXPECT_FALSE(device_->store()->Contains(""));
Chris Masone853b81b2011-06-24 14:11:41 -070059}
60
mukesh agrawal31950242011-07-14 11:53:38 -070061TEST_F(WiFiPropertyTest, Dispatch) {
Chris Masonea8a2c252011-06-27 22:16:30 -070062 {
63 ::DBus::Error error;
Chris Masone27c4aa52011-07-02 13:10:14 -070064 EXPECT_TRUE(DBusAdaptor::DispatchOnType(device_->store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070065 flimflam::kBgscanMethodProperty,
66 PropertyStoreTest::kStringV,
67 &error));
68 }
69 {
70 ::DBus::Error error;
71 EXPECT_TRUE(DBusAdaptor::DispatchOnType(
Chris Masone27c4aa52011-07-02 13:10:14 -070072 device_->store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070073 flimflam::kBgscanSignalThresholdProperty,
74 PropertyStoreTest::kInt32V,
75 &error));
76 }
77 {
78 ::DBus::Error error;
Chris Masone27c4aa52011-07-02 13:10:14 -070079 EXPECT_TRUE(DBusAdaptor::DispatchOnType(device_->store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070080 flimflam::kScanIntervalProperty,
81 PropertyStoreTest::kUint16V,
82 &error));
83 }
Chris Masone853b81b2011-06-24 14:11:41 -070084 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -070085 {
86 ::DBus::Error error;
Chris Masone27c4aa52011-07-02 13:10:14 -070087 EXPECT_FALSE(DBusAdaptor::DispatchOnType(device_->store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070088 flimflam::kScanningProperty,
89 PropertyStoreTest::kBoolV,
90 &error));
91 EXPECT_EQ(invalid_args_, error.name());
92 }
Chris Masone853b81b2011-06-24 14:11:41 -070093}
94
mukesh agrawal31950242011-07-14 11:53:38 -070095class WiFiMainTest : public Test {
96 public:
97 WiFiMainTest()
98 : manager_(&control_interface_, NULL, NULL),
Chris Masone626719f2011-08-18 16:58:48 -070099 wifi_(new WiFi(&control_interface_,
100 NULL,
101 &manager_,
102 kDeviceName,
103 kDeviceAddress,
104 0)),
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700105 supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()),
106 supplicant_interface_proxy_(
107 new NiceMock<MockSupplicantInterfaceProxy>(wifi_)),
108 proxy_factory_(this) {
mukesh agrawal31950242011-07-14 11:53:38 -0700109 ProxyFactory::set_factory(&proxy_factory_);
110 ::testing::DefaultValue< ::DBus::Path>::Set("/default/path");
111 }
112 virtual ~WiFiMainTest() {
113 // must Stop WiFi instance, to clear its list of services.
114 // otherwise, the WiFi instance will not be deleted. (because
115 // services reference a WiFi instance, creating a cycle.)
116 wifi_->Stop();
117 }
118
mukesh agrawal31950242011-07-14 11:53:38 -0700119 protected:
120 class TestProxyFactory : public ProxyFactory {
121 public:
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700122 TestProxyFactory(WiFiMainTest *test) : test_(test) {}
mukesh agrawal31950242011-07-14 11:53:38 -0700123
124 virtual SupplicantProcessProxyInterface *CreateSupplicantProcessProxy(
125 const char *dbus_path, const char *dbus_addr) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700126 return test_->supplicant_process_proxy_.release();
mukesh agrawal31950242011-07-14 11:53:38 -0700127 }
128
129 virtual SupplicantInterfaceProxyInterface *CreateSupplicantInterfaceProxy(
130 const WiFiRefPtr &wifi,
131 const DBus::Path &object_path,
132 const char *dbus_addr) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700133 return test_->supplicant_interface_proxy_.release();
mukesh agrawal31950242011-07-14 11:53:38 -0700134 }
135
136 private:
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700137 WiFiMainTest *test_;
mukesh agrawal31950242011-07-14 11:53:38 -0700138 };
139
140 const WiFi::EndpointMap &GetEndpointMap() {
141 return wifi_->endpoint_by_bssid_;
142 }
143 const WiFi::ServiceMap &GetServiceMap() {
144 return wifi_->service_by_private_id_;
145 }
146 // note: the tests need the proxies referenced by WiFi (not the
147 // proxies instantiated by WiFiMainTest), to ensure that WiFi
148 // sets up its proxies correctly.
149 SupplicantProcessProxyInterface *GetSupplicantProcessProxy() {
150 return wifi_->supplicant_process_proxy_.get();
151 }
152 SupplicantInterfaceProxyInterface *GetSupplicantInterfaceProxy() {
153 return wifi_->supplicant_interface_proxy_.get();
154 }
155 void InitiateConnect(const WiFiService &service) {
156 wifi_->ConnectTo(service);
157 }
158 void ReportBSS(const ::DBus::Path &bss_path,
159 const string &ssid,
160 const string &bssid,
161 int16_t signal_strength,
162 const char *mode);
163 void ReportScanDone() {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700164 wifi_->ScanDoneTask();
mukesh agrawal31950242011-07-14 11:53:38 -0700165 }
166 void StartWiFi() {
167 wifi_->Start();
mukesh agrawal31950242011-07-14 11:53:38 -0700168 }
169 void StopWiFi() {
170 wifi_->Stop();
171 }
172
173 private:
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700174 NiceMockControl control_interface_;
Chris Masone2ae797d2011-08-23 20:41:00 -0700175 MockManager manager_;
mukesh agrawal31950242011-07-14 11:53:38 -0700176 WiFiRefPtr wifi_;
mukesh agrawal31950242011-07-14 11:53:38 -0700177
178 // protected fields interspersed between private fields, due to
179 // initialization order
180 protected:
181 static const char kDeviceName[];
Chris Masone626719f2011-08-18 16:58:48 -0700182 static const char kDeviceAddress[];
mukesh agrawal31950242011-07-14 11:53:38 -0700183 static const char kNetworkModeAdHoc[];
184 static const char kNetworkModeInfrastructure[];
185
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700186 scoped_ptr<MockSupplicantProcessProxy> supplicant_process_proxy_;
187 scoped_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
mukesh agrawal31950242011-07-14 11:53:38 -0700188
189 private:
190 TestProxyFactory proxy_factory_;
191
192};
193
194const char WiFiMainTest::kDeviceName[] = "wlan0";
Chris Masone626719f2011-08-18 16:58:48 -0700195const char WiFiMainTest::kDeviceAddress[] = "00:01:02:03:04:05";
mukesh agrawal31950242011-07-14 11:53:38 -0700196const char WiFiMainTest::kNetworkModeAdHoc[] = "ad-hoc";
197const char WiFiMainTest::kNetworkModeInfrastructure[] = "infrastructure";
198
199void WiFiMainTest::ReportBSS(const ::DBus::Path &bss_path,
200 const string &ssid,
201 const string &bssid,
202 int16_t signal_strength,
203 const char *mode) {
204 map<string, ::DBus::Variant> bss_properties;
205
206 {
207 DBus::MessageIter writer(bss_properties["SSID"].writer());
208 writer << vector<uint8_t>(ssid.begin(), ssid.end());
209 }
210 {
211 string bssid_nosep;
212 vector<uint8_t> bssid_bytes;
213 RemoveChars(bssid, ":", &bssid_nosep);
214 base::HexStringToBytes(bssid_nosep, &bssid_bytes);
215
216 DBus::MessageIter writer(bss_properties["BSSID"].writer());
217 writer << bssid_bytes;
218 }
219 bss_properties["Signal"].writer().append_int16(signal_strength);
220 bss_properties["Mode"].writer().append_string(mode);
221 wifi_->BSSAdded(bss_path, bss_properties);
222}
223
224TEST_F(WiFiMainTest, ProxiesSetUpDuringStart) {
225 EXPECT_TRUE(GetSupplicantProcessProxy() == NULL);
226 EXPECT_TRUE(GetSupplicantInterfaceProxy() == NULL);
227
228 StartWiFi();
229 EXPECT_FALSE(GetSupplicantProcessProxy() == NULL);
230 EXPECT_FALSE(GetSupplicantInterfaceProxy() == NULL);
231}
232
233TEST_F(WiFiMainTest, CleanStart) {
234 EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_));
235 EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_))
236 .Times(AnyNumber())
237 .WillRepeatedly(Throw(
238 DBus::Error(
239 "fi.w1.wpa_supplicant1.InterfaceUnknown",
240 "test threw fi.w1.wpa_supplicant1.InterfaceUnknown")));
241 EXPECT_CALL(*supplicant_interface_proxy_, Scan(_));
242 StartWiFi();
243}
244
245TEST_F(WiFiMainTest, Restart) {
246 EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_))
247 .Times(AnyNumber())
248 .WillRepeatedly(Throw(
249 DBus::Error(
250 "fi.w1.wpa_supplicant1.InterfaceExists",
251 "test thew fi.w1.wpa_supplicant1.InterfaceExists")));
252 EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_));
253 EXPECT_CALL(*supplicant_interface_proxy_, Scan(_));
254 StartWiFi();
255}
256
257TEST_F(WiFiMainTest, StartClearsState) {
258 EXPECT_CALL(*supplicant_interface_proxy_, RemoveAllNetworks());
259 EXPECT_CALL(*supplicant_interface_proxy_, FlushBSS(_));
260 StartWiFi();
261}
262
263TEST_F(WiFiMainTest, ScanResults) {
264 StartWiFi();
265 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
266 ReportBSS(
267 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
268 ReportBSS(
269 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
270 ReportBSS(
271 "bss3", "ssid3", "00:00:00:00:00:03", 3, kNetworkModeInfrastructure);
272 ReportBSS("bss4", "ssid4", "00:00:00:00:00:04", 4, kNetworkModeAdHoc);
273 EXPECT_EQ(5, GetEndpointMap().size());
274}
275
276TEST_F(WiFiMainTest, ScanResultsWithUpdates) {
277 StartWiFi();
278 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
279 ReportBSS(
280 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
281 ReportBSS(
282 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
283 ReportBSS(
284 "bss1", "ssid1", "00:00:00:00:00:01", 3, kNetworkModeInfrastructure);
285 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 4, kNetworkModeAdHoc);
286 EXPECT_EQ(3, GetEndpointMap().size());
287 ASSERT_TRUE(ContainsKey(GetEndpointMap(), "000000000000"));
288 EXPECT_EQ(4, GetEndpointMap().find("000000000000")->second->
289 signal_strength());
290}
291
292TEST_F(WiFiMainTest, ScanCompleted) {
293 StartWiFi();
294 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
295 ReportBSS(
296 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
297 ReportBSS(
298 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
299 ReportScanDone();
300 EXPECT_EQ(3, GetServiceMap().size());
301}
302
303TEST_F(WiFiMainTest, Connect) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700304 MockSupplicantInterfaceProxy &supplicant_interface_proxy =
305 *supplicant_interface_proxy_;
306
mukesh agrawal31950242011-07-14 11:53:38 -0700307 StartWiFi();
308 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
309 ReportScanDone();
310
311 {
312 InSequence s;
313 DBus::Path fake_path("/fake/path");
314
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700315 EXPECT_CALL(supplicant_interface_proxy, AddNetwork(_))
mukesh agrawal31950242011-07-14 11:53:38 -0700316 .WillOnce(Return(fake_path));
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700317 EXPECT_CALL(supplicant_interface_proxy, SelectNetwork(fake_path));
mukesh agrawal31950242011-07-14 11:53:38 -0700318 InitiateConnect(*(GetServiceMap().begin()->second));
319 }
320}
321
Chris Masone853b81b2011-06-24 14:11:41 -0700322} // namespace shill