blob: 292d3850f5654e372af31d28c33e8908de3747dc [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
mukesh agrawalf2f68a52011-09-01 12:15:48 -07007#include <netinet/ether.h>
8#include <linux/if.h>
9
Chris Masone853b81b2011-06-24 14:11:41 -070010#include <map>
11#include <string>
12#include <vector>
13
mukesh agrawaldc42bb32011-07-28 10:40:26 -070014#include <base/memory/scoped_ptr.h>
mukesh agrawal31950242011-07-14 11:53:38 -070015#include <base/string_number_conversions.h>
16#include <base/string_util.h>
Chris Masone853b81b2011-06-24 14:11:41 -070017#include <dbus-c++/dbus.h>
18#include <chromeos/dbus/service_constants.h>
Chris Masone7156c922011-08-23 20:36:21 -070019#include <gmock/gmock.h>
Chris Masone2ae797d2011-08-23 20:41:00 -070020#include <gtest/gtest.h>
Chris Masone853b81b2011-06-24 14:11:41 -070021
22#include "shill/dbus_adaptor.h"
23#include "shill/manager.h"
Chris Masone853b81b2011-06-24 14:11:41 -070024#include "shill/mock_device.h"
mukesh agrawalf2f68a52011-09-01 12:15:48 -070025#include "shill/mock_dhcp_config.h"
26#include "shill/mock_dhcp_provider.h"
Chris Masone2ae797d2011-08-23 20:41:00 -070027#include "shill/mock_manager.h"
mukesh agrawal31950242011-07-14 11:53:38 -070028#include "shill/mock_supplicant_interface_proxy.h"
29#include "shill/mock_supplicant_process_proxy.h"
mukesh agrawaldc42bb32011-07-28 10:40:26 -070030#include "shill/nice_mock_control.h"
Chris Masone853b81b2011-06-24 14:11:41 -070031#include "shill/property_store_unittest.h"
mukesh agrawal31950242011-07-14 11:53:38 -070032#include "shill/proxy_factory.h"
33#include "shill/wifi_endpoint.h"
34#include "shill/wifi.h"
mukesh agrawal32399322011-09-01 10:53:43 -070035#include "shill/wifi_service.h"
Chris Masone853b81b2011-06-24 14:11:41 -070036
37using std::map;
38using std::string;
39using std::vector;
40using ::testing::_;
mukesh agrawal31950242011-07-14 11:53:38 -070041using ::testing::AnyNumber;
42using ::testing::DefaultValue;
43using ::testing::InSequence;
mukesh agrawaldc42bb32011-07-28 10:40:26 -070044using ::testing::NiceMock;
Chris Masone853b81b2011-06-24 14:11:41 -070045using ::testing::Return;
46using ::testing::Test;
mukesh agrawal31950242011-07-14 11:53:38 -070047using ::testing::Throw;
Chris Masone853b81b2011-06-24 14:11:41 -070048
49namespace shill {
50
mukesh agrawal31950242011-07-14 11:53:38 -070051class WiFiPropertyTest : public PropertyStoreTest {
Chris Masone853b81b2011-06-24 14:11:41 -070052 public:
mukesh agrawal31950242011-07-14 11:53:38 -070053 WiFiPropertyTest()
Chris Masone2176a882011-09-14 22:29:15 -070054 : device_(new WiFi(control_interface(), NULL, NULL, "wifi", "", 0)) {
Chris Masone853b81b2011-06-24 14:11:41 -070055 }
mukesh agrawal31950242011-07-14 11:53:38 -070056 virtual ~WiFiPropertyTest() {}
Chris Masone853b81b2011-06-24 14:11:41 -070057
58 protected:
59 DeviceRefPtr device_;
60};
61
mukesh agrawal31950242011-07-14 11:53:38 -070062TEST_F(WiFiPropertyTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -070063 EXPECT_TRUE(device_->store().Contains(flimflam::kNameProperty));
64 EXPECT_FALSE(device_->store().Contains(""));
Chris Masone853b81b2011-06-24 14:11:41 -070065}
66
mukesh agrawal31950242011-07-14 11:53:38 -070067TEST_F(WiFiPropertyTest, Dispatch) {
Chris Masonea8a2c252011-06-27 22:16:30 -070068 {
69 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -070070 EXPECT_TRUE(DBusAdaptor::DispatchOnType(device_->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070071 flimflam::kBgscanMethodProperty,
72 PropertyStoreTest::kStringV,
73 &error));
74 }
75 {
76 ::DBus::Error error;
77 EXPECT_TRUE(DBusAdaptor::DispatchOnType(
mukesh agrawalde29fa82011-09-16 16:16:36 -070078 device_->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070079 flimflam::kBgscanSignalThresholdProperty,
80 PropertyStoreTest::kInt32V,
81 &error));
82 }
83 {
84 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -070085 EXPECT_TRUE(DBusAdaptor::DispatchOnType(device_->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070086 flimflam::kScanIntervalProperty,
87 PropertyStoreTest::kUint16V,
88 &error));
89 }
Chris Masone853b81b2011-06-24 14:11:41 -070090 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -070091 {
92 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -070093 EXPECT_FALSE(DBusAdaptor::DispatchOnType(device_->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070094 flimflam::kScanningProperty,
95 PropertyStoreTest::kBoolV,
96 &error));
Chris Masone9d779932011-08-25 16:33:41 -070097 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -070098 }
Chris Masone853b81b2011-06-24 14:11:41 -070099}
100
mukesh agrawal31950242011-07-14 11:53:38 -0700101class WiFiMainTest : public Test {
102 public:
103 WiFiMainTest()
104 : manager_(&control_interface_, NULL, NULL),
Chris Masone626719f2011-08-18 16:58:48 -0700105 wifi_(new WiFi(&control_interface_,
mukesh agrawal32399322011-09-01 10:53:43 -0700106 &dispatcher_,
Chris Masone626719f2011-08-18 16:58:48 -0700107 &manager_,
108 kDeviceName,
109 kDeviceAddress,
110 0)),
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700111 supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()),
112 supplicant_interface_proxy_(
113 new NiceMock<MockSupplicantInterfaceProxy>(wifi_)),
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700114 dhcp_config_(new MockDHCPConfig(&control_interface_,
115 &dispatcher_,
116 &dhcp_provider_,
117 kDeviceName,
118 &glib_)),
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700119 proxy_factory_(this) {
mukesh agrawal31950242011-07-14 11:53:38 -0700120 ProxyFactory::set_factory(&proxy_factory_);
121 ::testing::DefaultValue< ::DBus::Path>::Set("/default/path");
122 }
123 virtual ~WiFiMainTest() {
124 // must Stop WiFi instance, to clear its list of services.
125 // otherwise, the WiFi instance will not be deleted. (because
126 // services reference a WiFi instance, creating a cycle.)
127 wifi_->Stop();
128 }
129
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700130 virtual void SetUp() {
131 wifi_->set_dhcp_provider(&dhcp_provider_);
132 }
133
mukesh agrawal31950242011-07-14 11:53:38 -0700134 protected:
135 class TestProxyFactory : public ProxyFactory {
136 public:
Paul Stewart7355ce12011-09-02 10:47:01 -0700137 explicit TestProxyFactory(WiFiMainTest *test) : test_(test) {}
mukesh agrawal31950242011-07-14 11:53:38 -0700138
139 virtual SupplicantProcessProxyInterface *CreateSupplicantProcessProxy(
140 const char *dbus_path, const char *dbus_addr) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700141 return test_->supplicant_process_proxy_.release();
mukesh agrawal31950242011-07-14 11:53:38 -0700142 }
143
144 virtual SupplicantInterfaceProxyInterface *CreateSupplicantInterfaceProxy(
145 const WiFiRefPtr &wifi,
146 const DBus::Path &object_path,
147 const char *dbus_addr) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700148 return test_->supplicant_interface_proxy_.release();
mukesh agrawal31950242011-07-14 11:53:38 -0700149 }
150
151 private:
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700152 WiFiMainTest *test_;
mukesh agrawal31950242011-07-14 11:53:38 -0700153 };
154
155 const WiFi::EndpointMap &GetEndpointMap() {
156 return wifi_->endpoint_by_bssid_;
157 }
158 const WiFi::ServiceMap &GetServiceMap() {
159 return wifi_->service_by_private_id_;
160 }
161 // note: the tests need the proxies referenced by WiFi (not the
162 // proxies instantiated by WiFiMainTest), to ensure that WiFi
163 // sets up its proxies correctly.
164 SupplicantProcessProxyInterface *GetSupplicantProcessProxy() {
165 return wifi_->supplicant_process_proxy_.get();
166 }
167 SupplicantInterfaceProxyInterface *GetSupplicantInterfaceProxy() {
168 return wifi_->supplicant_interface_proxy_.get();
169 }
mukesh agrawal32399322011-09-01 10:53:43 -0700170 void InitiateConnect(WiFiService *service) {
mukesh agrawal31950242011-07-14 11:53:38 -0700171 wifi_->ConnectTo(service);
172 }
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700173 bool IsLinkUp() {
174 return wifi_->link_up_;
175 }
mukesh agrawal31950242011-07-14 11:53:38 -0700176 void ReportBSS(const ::DBus::Path &bss_path,
177 const string &ssid,
178 const string &bssid,
179 int16_t signal_strength,
180 const char *mode);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700181 void ReportLinkUp() {
182 wifi_->LinkEvent(IFF_LOWER_UP, IFF_LOWER_UP);
183 }
mukesh agrawal31950242011-07-14 11:53:38 -0700184 void ReportScanDone() {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700185 wifi_->ScanDoneTask();
mukesh agrawal31950242011-07-14 11:53:38 -0700186 }
187 void StartWiFi() {
188 wifi_->Start();
mukesh agrawal31950242011-07-14 11:53:38 -0700189 }
190 void StopWiFi() {
191 wifi_->Stop();
192 }
mukesh agrawal32399322011-09-01 10:53:43 -0700193 MockManager *manager() {
194 return &manager_;
195 }
196 const WiFiConstRefPtr wifi() const {
197 return wifi_;
198 }
199
200 EventDispatcher dispatcher_;
mukesh agrawal31950242011-07-14 11:53:38 -0700201
202 private:
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700203 NiceMockControl control_interface_;
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700204 MockGLib glib_;
Chris Masone2ae797d2011-08-23 20:41:00 -0700205 MockManager manager_;
mukesh agrawal31950242011-07-14 11:53:38 -0700206 WiFiRefPtr wifi_;
mukesh agrawal31950242011-07-14 11:53:38 -0700207
208 // protected fields interspersed between private fields, due to
209 // initialization order
210 protected:
211 static const char kDeviceName[];
Chris Masone626719f2011-08-18 16:58:48 -0700212 static const char kDeviceAddress[];
mukesh agrawal31950242011-07-14 11:53:38 -0700213 static const char kNetworkModeAdHoc[];
214 static const char kNetworkModeInfrastructure[];
215
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700216 scoped_ptr<MockSupplicantProcessProxy> supplicant_process_proxy_;
217 scoped_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700218 MockDHCPProvider dhcp_provider_;
219 scoped_refptr<MockDHCPConfig> dhcp_config_;
mukesh agrawal31950242011-07-14 11:53:38 -0700220
221 private:
222 TestProxyFactory proxy_factory_;
mukesh agrawal31950242011-07-14 11:53:38 -0700223};
224
225const char WiFiMainTest::kDeviceName[] = "wlan0";
Chris Masone626719f2011-08-18 16:58:48 -0700226const char WiFiMainTest::kDeviceAddress[] = "00:01:02:03:04:05";
mukesh agrawal31950242011-07-14 11:53:38 -0700227const char WiFiMainTest::kNetworkModeAdHoc[] = "ad-hoc";
228const char WiFiMainTest::kNetworkModeInfrastructure[] = "infrastructure";
229
230void WiFiMainTest::ReportBSS(const ::DBus::Path &bss_path,
231 const string &ssid,
232 const string &bssid,
233 int16_t signal_strength,
234 const char *mode) {
235 map<string, ::DBus::Variant> bss_properties;
236
237 {
238 DBus::MessageIter writer(bss_properties["SSID"].writer());
239 writer << vector<uint8_t>(ssid.begin(), ssid.end());
240 }
241 {
242 string bssid_nosep;
243 vector<uint8_t> bssid_bytes;
244 RemoveChars(bssid, ":", &bssid_nosep);
245 base::HexStringToBytes(bssid_nosep, &bssid_bytes);
246
247 DBus::MessageIter writer(bss_properties["BSSID"].writer());
248 writer << bssid_bytes;
249 }
250 bss_properties["Signal"].writer().append_int16(signal_strength);
251 bss_properties["Mode"].writer().append_string(mode);
252 wifi_->BSSAdded(bss_path, bss_properties);
253}
254
255TEST_F(WiFiMainTest, ProxiesSetUpDuringStart) {
256 EXPECT_TRUE(GetSupplicantProcessProxy() == NULL);
257 EXPECT_TRUE(GetSupplicantInterfaceProxy() == NULL);
258
259 StartWiFi();
260 EXPECT_FALSE(GetSupplicantProcessProxy() == NULL);
261 EXPECT_FALSE(GetSupplicantInterfaceProxy() == NULL);
262}
263
264TEST_F(WiFiMainTest, CleanStart) {
265 EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_));
266 EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_))
267 .Times(AnyNumber())
268 .WillRepeatedly(Throw(
269 DBus::Error(
270 "fi.w1.wpa_supplicant1.InterfaceUnknown",
271 "test threw fi.w1.wpa_supplicant1.InterfaceUnknown")));
272 EXPECT_CALL(*supplicant_interface_proxy_, Scan(_));
273 StartWiFi();
mukesh agrawal32399322011-09-01 10:53:43 -0700274 dispatcher_.DispatchPendingEvents();
mukesh agrawal31950242011-07-14 11:53:38 -0700275}
276
277TEST_F(WiFiMainTest, Restart) {
278 EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_))
279 .Times(AnyNumber())
280 .WillRepeatedly(Throw(
281 DBus::Error(
282 "fi.w1.wpa_supplicant1.InterfaceExists",
283 "test thew fi.w1.wpa_supplicant1.InterfaceExists")));
284 EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_));
285 EXPECT_CALL(*supplicant_interface_proxy_, Scan(_));
286 StartWiFi();
mukesh agrawal32399322011-09-01 10:53:43 -0700287 dispatcher_.DispatchPendingEvents();
mukesh agrawal31950242011-07-14 11:53:38 -0700288}
289
290TEST_F(WiFiMainTest, StartClearsState) {
291 EXPECT_CALL(*supplicant_interface_proxy_, RemoveAllNetworks());
292 EXPECT_CALL(*supplicant_interface_proxy_, FlushBSS(_));
293 StartWiFi();
294}
295
296TEST_F(WiFiMainTest, ScanResults) {
297 StartWiFi();
298 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
299 ReportBSS(
300 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
301 ReportBSS(
302 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
303 ReportBSS(
304 "bss3", "ssid3", "00:00:00:00:00:03", 3, kNetworkModeInfrastructure);
305 ReportBSS("bss4", "ssid4", "00:00:00:00:00:04", 4, kNetworkModeAdHoc);
306 EXPECT_EQ(5, GetEndpointMap().size());
307}
308
309TEST_F(WiFiMainTest, ScanResultsWithUpdates) {
310 StartWiFi();
311 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
312 ReportBSS(
313 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
314 ReportBSS(
315 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
316 ReportBSS(
317 "bss1", "ssid1", "00:00:00:00:00:01", 3, kNetworkModeInfrastructure);
318 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 4, kNetworkModeAdHoc);
319 EXPECT_EQ(3, GetEndpointMap().size());
320 ASSERT_TRUE(ContainsKey(GetEndpointMap(), "000000000000"));
321 EXPECT_EQ(4, GetEndpointMap().find("000000000000")->second->
322 signal_strength());
323}
324
325TEST_F(WiFiMainTest, ScanCompleted) {
326 StartWiFi();
327 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
328 ReportBSS(
329 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
330 ReportBSS(
331 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
mukesh agrawal32399322011-09-01 10:53:43 -0700332 EXPECT_CALL(*manager(), RegisterService(_))
333 .Times(3);
mukesh agrawal31950242011-07-14 11:53:38 -0700334 ReportScanDone();
335 EXPECT_EQ(3, GetServiceMap().size());
336}
337
338TEST_F(WiFiMainTest, Connect) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700339 MockSupplicantInterfaceProxy &supplicant_interface_proxy =
340 *supplicant_interface_proxy_;
341
mukesh agrawal31950242011-07-14 11:53:38 -0700342 StartWiFi();
343 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
344 ReportScanDone();
345
346 {
347 InSequence s;
348 DBus::Path fake_path("/fake/path");
mukesh agrawal32399322011-09-01 10:53:43 -0700349 WiFiService *service(GetServiceMap().begin()->second);
mukesh agrawal31950242011-07-14 11:53:38 -0700350
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700351 EXPECT_CALL(supplicant_interface_proxy, AddNetwork(_))
mukesh agrawal31950242011-07-14 11:53:38 -0700352 .WillOnce(Return(fake_path));
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700353 EXPECT_CALL(supplicant_interface_proxy, SelectNetwork(fake_path));
mukesh agrawal32399322011-09-01 10:53:43 -0700354 InitiateConnect(service);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700355 EXPECT_EQ(static_cast<Service *>(service),
356 wifi()->selected_service_.get());
mukesh agrawal31950242011-07-14 11:53:38 -0700357 }
358}
359
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700360TEST_F(WiFiMainTest, LinkEvent) {
361 EXPECT_FALSE(IsLinkUp());
362 EXPECT_CALL(dhcp_provider_, CreateConfig(_)).
363 WillOnce(Return(dhcp_config_));
364 ReportLinkUp();
365}
366
Chris Masone853b81b2011-06-24 14:11:41 -0700367} // namespace shill