blob: 18039e5b47d8b509ed04e9ada57b3e280e3f5c29 [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>
16#include <gtest/gtest.h>
17#include <gmock/gmock.h>
18
19#include "shill/dbus_adaptor.h"
20#include "shill/manager.h"
Chris Masone853b81b2011-06-24 14:11:41 -070021#include "shill/mock_device.h"
mukesh agrawal31950242011-07-14 11:53:38 -070022#include "shill/mock_supplicant_interface_proxy.h"
23#include "shill/mock_supplicant_process_proxy.h"
mukesh agrawaldc42bb32011-07-28 10:40:26 -070024#include "shill/nice_mock_control.h"
Chris Masone853b81b2011-06-24 14:11:41 -070025#include "shill/property_store_unittest.h"
mukesh agrawal31950242011-07-14 11:53:38 -070026#include "shill/proxy_factory.h"
27#include "shill/wifi_endpoint.h"
28#include "shill/wifi.h"
Chris Masone853b81b2011-06-24 14:11:41 -070029
30using std::map;
31using std::string;
32using std::vector;
33using ::testing::_;
mukesh agrawal31950242011-07-14 11:53:38 -070034using ::testing::AnyNumber;
35using ::testing::DefaultValue;
36using ::testing::InSequence;
mukesh agrawaldc42bb32011-07-28 10:40:26 -070037using ::testing::NiceMock;
Chris Masone853b81b2011-06-24 14:11:41 -070038using ::testing::Return;
39using ::testing::Test;
mukesh agrawal31950242011-07-14 11:53:38 -070040using ::testing::Throw;
Chris Masone853b81b2011-06-24 14:11:41 -070041
42namespace shill {
43
mukesh agrawal31950242011-07-14 11:53:38 -070044class WiFiPropertyTest : public PropertyStoreTest {
Chris Masone853b81b2011-06-24 14:11:41 -070045 public:
mukesh agrawal31950242011-07-14 11:53:38 -070046 WiFiPropertyTest()
Chris Masone853b81b2011-06-24 14:11:41 -070047 : device_(new WiFi(&control_interface_, NULL, NULL, "wifi", 0)) {
48 }
mukesh agrawal31950242011-07-14 11:53:38 -070049 virtual ~WiFiPropertyTest() {}
Chris Masone853b81b2011-06-24 14:11:41 -070050
51 protected:
52 DeviceRefPtr device_;
53};
54
mukesh agrawal31950242011-07-14 11:53:38 -070055TEST_F(WiFiPropertyTest, Contains) {
Chris Masone27c4aa52011-07-02 13:10:14 -070056 EXPECT_TRUE(device_->store()->Contains(flimflam::kNameProperty));
57 EXPECT_FALSE(device_->store()->Contains(""));
Chris Masone853b81b2011-06-24 14:11:41 -070058}
59
mukesh agrawal31950242011-07-14 11:53:38 -070060TEST_F(WiFiPropertyTest, Dispatch) {
Chris Masonea8a2c252011-06-27 22:16:30 -070061 {
62 ::DBus::Error error;
Chris Masone27c4aa52011-07-02 13:10:14 -070063 EXPECT_TRUE(DBusAdaptor::DispatchOnType(device_->store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070064 flimflam::kBgscanMethodProperty,
65 PropertyStoreTest::kStringV,
66 &error));
67 }
68 {
69 ::DBus::Error error;
70 EXPECT_TRUE(DBusAdaptor::DispatchOnType(
Chris Masone27c4aa52011-07-02 13:10:14 -070071 device_->store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070072 flimflam::kBgscanSignalThresholdProperty,
73 PropertyStoreTest::kInt32V,
74 &error));
75 }
76 {
77 ::DBus::Error error;
Chris Masone27c4aa52011-07-02 13:10:14 -070078 EXPECT_TRUE(DBusAdaptor::DispatchOnType(device_->store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070079 flimflam::kScanIntervalProperty,
80 PropertyStoreTest::kUint16V,
81 &error));
82 }
Chris Masone853b81b2011-06-24 14:11:41 -070083 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -070084 {
85 ::DBus::Error error;
Chris Masone27c4aa52011-07-02 13:10:14 -070086 EXPECT_FALSE(DBusAdaptor::DispatchOnType(device_->store(),
Chris Masonea8a2c252011-06-27 22:16:30 -070087 flimflam::kScanningProperty,
88 PropertyStoreTest::kBoolV,
89 &error));
90 EXPECT_EQ(invalid_args_, error.name());
91 }
Chris Masone853b81b2011-06-24 14:11:41 -070092}
93
mukesh agrawal31950242011-07-14 11:53:38 -070094class WiFiMainTest : public Test {
95 public:
96 WiFiMainTest()
97 : manager_(&control_interface_, NULL, NULL),
98 wifi_(new WiFi(&control_interface_, NULL, &manager_, kDeviceName, 0)),
mukesh agrawaldc42bb32011-07-28 10:40:26 -070099 supplicant_process_proxy_(new NiceMock<MockSupplicantProcessProxy>()),
100 supplicant_interface_proxy_(
101 new NiceMock<MockSupplicantInterfaceProxy>(wifi_)),
102 proxy_factory_(this) {
mukesh agrawal31950242011-07-14 11:53:38 -0700103 ProxyFactory::set_factory(&proxy_factory_);
104 ::testing::DefaultValue< ::DBus::Path>::Set("/default/path");
105 }
106 virtual ~WiFiMainTest() {
107 // must Stop WiFi instance, to clear its list of services.
108 // otherwise, the WiFi instance will not be deleted. (because
109 // services reference a WiFi instance, creating a cycle.)
110 wifi_->Stop();
111 }
112
mukesh agrawal31950242011-07-14 11:53:38 -0700113 protected:
114 class TestProxyFactory : public ProxyFactory {
115 public:
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700116 TestProxyFactory(WiFiMainTest *test) : test_(test) {}
mukesh agrawal31950242011-07-14 11:53:38 -0700117
118 virtual SupplicantProcessProxyInterface *CreateSupplicantProcessProxy(
119 const char *dbus_path, const char *dbus_addr) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700120 return test_->supplicant_process_proxy_.release();
mukesh agrawal31950242011-07-14 11:53:38 -0700121 }
122
123 virtual SupplicantInterfaceProxyInterface *CreateSupplicantInterfaceProxy(
124 const WiFiRefPtr &wifi,
125 const DBus::Path &object_path,
126 const char *dbus_addr) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700127 return test_->supplicant_interface_proxy_.release();
mukesh agrawal31950242011-07-14 11:53:38 -0700128 }
129
130 private:
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700131 WiFiMainTest *test_;
mukesh agrawal31950242011-07-14 11:53:38 -0700132 };
133
134 const WiFi::EndpointMap &GetEndpointMap() {
135 return wifi_->endpoint_by_bssid_;
136 }
137 const WiFi::ServiceMap &GetServiceMap() {
138 return wifi_->service_by_private_id_;
139 }
140 // note: the tests need the proxies referenced by WiFi (not the
141 // proxies instantiated by WiFiMainTest), to ensure that WiFi
142 // sets up its proxies correctly.
143 SupplicantProcessProxyInterface *GetSupplicantProcessProxy() {
144 return wifi_->supplicant_process_proxy_.get();
145 }
146 SupplicantInterfaceProxyInterface *GetSupplicantInterfaceProxy() {
147 return wifi_->supplicant_interface_proxy_.get();
148 }
149 void InitiateConnect(const WiFiService &service) {
150 wifi_->ConnectTo(service);
151 }
152 void ReportBSS(const ::DBus::Path &bss_path,
153 const string &ssid,
154 const string &bssid,
155 int16_t signal_strength,
156 const char *mode);
157 void ReportScanDone() {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700158 wifi_->ScanDoneTask();
mukesh agrawal31950242011-07-14 11:53:38 -0700159 }
160 void StartWiFi() {
161 wifi_->Start();
mukesh agrawal31950242011-07-14 11:53:38 -0700162 }
163 void StopWiFi() {
164 wifi_->Stop();
165 }
166
167 private:
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700168 NiceMockControl control_interface_;
mukesh agrawal31950242011-07-14 11:53:38 -0700169 Manager manager_;
170 WiFiRefPtr wifi_;
mukesh agrawal31950242011-07-14 11:53:38 -0700171
172 // protected fields interspersed between private fields, due to
173 // initialization order
174 protected:
175 static const char kDeviceName[];
176 static const char kNetworkModeAdHoc[];
177 static const char kNetworkModeInfrastructure[];
178
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700179 scoped_ptr<MockSupplicantProcessProxy> supplicant_process_proxy_;
180 scoped_ptr<MockSupplicantInterfaceProxy> supplicant_interface_proxy_;
mukesh agrawal31950242011-07-14 11:53:38 -0700181
182 private:
183 TestProxyFactory proxy_factory_;
184
185};
186
187const char WiFiMainTest::kDeviceName[] = "wlan0";
188const char WiFiMainTest::kNetworkModeAdHoc[] = "ad-hoc";
189const char WiFiMainTest::kNetworkModeInfrastructure[] = "infrastructure";
190
191void WiFiMainTest::ReportBSS(const ::DBus::Path &bss_path,
192 const string &ssid,
193 const string &bssid,
194 int16_t signal_strength,
195 const char *mode) {
196 map<string, ::DBus::Variant> bss_properties;
197
198 {
199 DBus::MessageIter writer(bss_properties["SSID"].writer());
200 writer << vector<uint8_t>(ssid.begin(), ssid.end());
201 }
202 {
203 string bssid_nosep;
204 vector<uint8_t> bssid_bytes;
205 RemoveChars(bssid, ":", &bssid_nosep);
206 base::HexStringToBytes(bssid_nosep, &bssid_bytes);
207
208 DBus::MessageIter writer(bss_properties["BSSID"].writer());
209 writer << bssid_bytes;
210 }
211 bss_properties["Signal"].writer().append_int16(signal_strength);
212 bss_properties["Mode"].writer().append_string(mode);
213 wifi_->BSSAdded(bss_path, bss_properties);
214}
215
216TEST_F(WiFiMainTest, ProxiesSetUpDuringStart) {
217 EXPECT_TRUE(GetSupplicantProcessProxy() == NULL);
218 EXPECT_TRUE(GetSupplicantInterfaceProxy() == NULL);
219
220 StartWiFi();
221 EXPECT_FALSE(GetSupplicantProcessProxy() == NULL);
222 EXPECT_FALSE(GetSupplicantInterfaceProxy() == NULL);
223}
224
225TEST_F(WiFiMainTest, CleanStart) {
226 EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_));
227 EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_))
228 .Times(AnyNumber())
229 .WillRepeatedly(Throw(
230 DBus::Error(
231 "fi.w1.wpa_supplicant1.InterfaceUnknown",
232 "test threw fi.w1.wpa_supplicant1.InterfaceUnknown")));
233 EXPECT_CALL(*supplicant_interface_proxy_, Scan(_));
234 StartWiFi();
235}
236
237TEST_F(WiFiMainTest, Restart) {
238 EXPECT_CALL(*supplicant_process_proxy_, CreateInterface(_))
239 .Times(AnyNumber())
240 .WillRepeatedly(Throw(
241 DBus::Error(
242 "fi.w1.wpa_supplicant1.InterfaceExists",
243 "test thew fi.w1.wpa_supplicant1.InterfaceExists")));
244 EXPECT_CALL(*supplicant_process_proxy_, GetInterface(_));
245 EXPECT_CALL(*supplicant_interface_proxy_, Scan(_));
246 StartWiFi();
247}
248
249TEST_F(WiFiMainTest, StartClearsState) {
250 EXPECT_CALL(*supplicant_interface_proxy_, RemoveAllNetworks());
251 EXPECT_CALL(*supplicant_interface_proxy_, FlushBSS(_));
252 StartWiFi();
253}
254
255TEST_F(WiFiMainTest, ScanResults) {
256 StartWiFi();
257 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
258 ReportBSS(
259 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
260 ReportBSS(
261 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
262 ReportBSS(
263 "bss3", "ssid3", "00:00:00:00:00:03", 3, kNetworkModeInfrastructure);
264 ReportBSS("bss4", "ssid4", "00:00:00:00:00:04", 4, kNetworkModeAdHoc);
265 EXPECT_EQ(5, GetEndpointMap().size());
266}
267
268TEST_F(WiFiMainTest, ScanResultsWithUpdates) {
269 StartWiFi();
270 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
271 ReportBSS(
272 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
273 ReportBSS(
274 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
275 ReportBSS(
276 "bss1", "ssid1", "00:00:00:00:00:01", 3, kNetworkModeInfrastructure);
277 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 4, kNetworkModeAdHoc);
278 EXPECT_EQ(3, GetEndpointMap().size());
279 ASSERT_TRUE(ContainsKey(GetEndpointMap(), "000000000000"));
280 EXPECT_EQ(4, GetEndpointMap().find("000000000000")->second->
281 signal_strength());
282}
283
284TEST_F(WiFiMainTest, ScanCompleted) {
285 StartWiFi();
286 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
287 ReportBSS(
288 "bss1", "ssid1", "00:00:00:00:00:01", 1, kNetworkModeInfrastructure);
289 ReportBSS(
290 "bss2", "ssid2", "00:00:00:00:00:02", 2, kNetworkModeInfrastructure);
291 ReportScanDone();
292 EXPECT_EQ(3, GetServiceMap().size());
293}
294
295TEST_F(WiFiMainTest, Connect) {
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700296 MockSupplicantInterfaceProxy &supplicant_interface_proxy =
297 *supplicant_interface_proxy_;
298
mukesh agrawal31950242011-07-14 11:53:38 -0700299 StartWiFi();
300 ReportBSS("bss0", "ssid0", "00:00:00:00:00:00", 0, kNetworkModeAdHoc);
301 ReportScanDone();
302
303 {
304 InSequence s;
305 DBus::Path fake_path("/fake/path");
306
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700307 EXPECT_CALL(supplicant_interface_proxy, AddNetwork(_))
mukesh agrawal31950242011-07-14 11:53:38 -0700308 .WillOnce(Return(fake_path));
mukesh agrawaldc42bb32011-07-28 10:40:26 -0700309 EXPECT_CALL(supplicant_interface_proxy, SelectNetwork(fake_path));
mukesh agrawal31950242011-07-14 11:53:38 -0700310 InitiateConnect(*(GetServiceMap().begin()->second));
311 }
312}
313
Chris Masone853b81b2011-06-24 14:11:41 -0700314} // namespace shill