blob: 0d71cbb028849923893354ffa219a778878c6a32 [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:
Paul Stewart7355ce12011-09-02 10:47:01 -0700122 explicit 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_;
mukesh agrawal31950242011-07-14 11:53:38 -0700191};
192
193const char WiFiMainTest::kDeviceName[] = "wlan0";
Chris Masone626719f2011-08-18 16:58:48 -0700194const char WiFiMainTest::kDeviceAddress[] = "00:01:02:03:04:05";
mukesh agrawal31950242011-07-14 11:53:38 -0700195const char WiFiMainTest::kNetworkModeAdHoc[] = "ad-hoc";
196const char WiFiMainTest::kNetworkModeInfrastructure[] = "infrastructure";
197
198void WiFiMainTest::ReportBSS(const ::DBus::Path &bss_path,
199 const string &ssid,
200 const string &bssid,
201 int16_t signal_strength,
202 const char *mode) {
203 map<string, ::DBus::Variant> bss_properties;
204
205 {
206 DBus::MessageIter writer(bss_properties["SSID"].writer());
207 writer << vector<uint8_t>(ssid.begin(), ssid.end());
208 }
209 {
210 string bssid_nosep;
211 vector<uint8_t> bssid_bytes;
212 RemoveChars(bssid, ":", &bssid_nosep);
213 base::HexStringToBytes(bssid_nosep, &bssid_bytes);
214
215 DBus::MessageIter writer(bss_properties["BSSID"].writer());
216 writer << bssid_bytes;
217 }
218 bss_properties["Signal"].writer().append_int16(signal_strength);
219 bss_properties["Mode"].writer().append_string(mode);
220 wifi_->BSSAdded(bss_path, bss_properties);
221}
222
223TEST_F(WiFiMainTest, ProxiesSetUpDuringStart) {
224 EXPECT_TRUE(GetSupplicantProcessProxy() == NULL);
225 EXPECT_TRUE(GetSupplicantInterfaceProxy() == NULL);
226
227 StartWiFi();
228 EXPECT_FALSE(GetSupplicantProcessProxy() == NULL);
229 EXPECT_FALSE(GetSupplicantInterfaceProxy() == NULL);
230}
231
232TEST_F(WiFiMainTest, CleanStart) {
233 EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_));
234 EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_))
235 .Times(AnyNumber())
236 .WillRepeatedly(Throw(
237 DBus::Error(
238 "fi.w1.wpa_supplicant1.InterfaceUnknown",
239 "test threw fi.w1.wpa_supplicant1.InterfaceUnknown")));
240 EXPECT_CALL(*supplicant_interface_proxy_, Scan(_));
241 StartWiFi();
242}
243
244TEST_F(WiFiMainTest, Restart) {
245 EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_))
246 .Times(AnyNumber())
247 .WillRepeatedly(Throw(
248 DBus::Error(
249 "fi.w1.wpa_supplicant1.InterfaceExists",
250 "test thew fi.w1.wpa_supplicant1.InterfaceExists")));
251 EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_));
252 EXPECT_CALL(*supplicant_interface_proxy_, Scan(_));
253 StartWiFi();
254}
255
256TEST_F(WiFiMainTest, StartClearsState) {
257 EXPECT_CALL(*supplicant_interface_proxy_, RemoveAllNetworks());
258 EXPECT_CALL(*supplicant_interface_proxy_, FlushBSS(_));
259 StartWiFi();
260}
261
262TEST_F(WiFiMainTest, ScanResults) {
263 StartWiFi();
264 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
265 ReportBSS(
266 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
267 ReportBSS(
268 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
269 ReportBSS(
270 "bss3", "ssid3", "00:00:00:00:00:03", 3, kNetworkModeInfrastructure);
271 ReportBSS("bss4", "ssid4", "00:00:00:00:00:04", 4, kNetworkModeAdHoc);
272 EXPECT_EQ(5, GetEndpointMap().size());
273}
274
275TEST_F(WiFiMainTest, ScanResultsWithUpdates) {
276 StartWiFi();
277 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
278 ReportBSS(
279 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
280 ReportBSS(
281 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
282 ReportBSS(
283 "bss1", "ssid1", "00:00:00:00:00:01", 3, kNetworkModeInfrastructure);
284 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 4, kNetworkModeAdHoc);
285 EXPECT_EQ(3, GetEndpointMap().size());
286 ASSERT_TRUE(ContainsKey(GetEndpointMap(), "000000000000"));
287 EXPECT_EQ(4, GetEndpointMap().find("000000000000")->second->
288 signal_strength());
289}
290
291TEST_F(WiFiMainTest, ScanCompleted) {
292 StartWiFi();
293 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
294 ReportBSS(
295 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
296 ReportBSS(
297 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
298 ReportScanDone();
299 EXPECT_EQ(3, GetServiceMap().size());
300}
301
302TEST_F(WiFiMainTest, Connect) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700303 MockSupplicantInterfaceProxy &supplicant_interface_proxy =
304 *supplicant_interface_proxy_;
305
mukesh agrawal31950242011-07-14 11:53:38 -0700306 StartWiFi();
307 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
308 ReportScanDone();
309
310 {
311 InSequence s;
312 DBus::Path fake_path("/fake/path");
313
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700314 EXPECT_CALL(supplicant_interface_proxy, AddNetwork(_))
mukesh agrawal31950242011-07-14 11:53:38 -0700315 .WillOnce(Return(fake_path));
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700316 EXPECT_CALL(supplicant_interface_proxy, SelectNetwork(fake_path));
mukesh agrawal31950242011-07-14 11:53:38 -0700317 InitiateConnect(*(GetServiceMap().begin()->second));
318 }
319}
320
Chris Masone853b81b2011-06-24 14:11:41 -0700321} // namespace shill