blob: 7d15437a46c6b5f17e86b41e7a5767b158688b61 [file] [log] [blame]
Darin Petkov33af05c2012-02-28 10:10:30 +01001// Copyright (c) 2012 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/vpn_service.h"
6
Darin Petkov02867712012-03-12 14:25:05 +01007#include <chromeos/dbus/service_constants.h>
Darin Petkov33af05c2012-02-28 10:10:30 +01008#include <gtest/gtest.h>
9
Darin Petkov9c6e9812013-03-26 13:49:07 +010010#include "shill/dbus_adaptor.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010011#include "shill/error.h"
12#include "shill/nice_mock_control.h"
13#include "shill/mock_adaptors.h"
Darin Petkov5eb05422012-05-11 15:45:25 +020014#include "shill/mock_connection.h"
15#include "shill/mock_device_info.h"
Darin Petkova0e645e2012-04-25 11:38:59 +020016#include "shill/mock_manager.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010017#include "shill/mock_metrics.h"
Darin Petkov9c6e9812013-03-26 13:49:07 +010018#include "shill/mock_profile.h"
Darin Petkov5eb05422012-05-11 15:45:25 +020019#include "shill/mock_sockets.h"
Darin Petkovf3c71d72012-03-21 12:32:15 +010020#include "shill/mock_store.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010021#include "shill/mock_vpn_driver.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070022#include "shill/mock_vpn_provider.h"
mukesh agrawalcbfb34e2013-04-17 19:33:25 -070023#include "shill/service_property_change_test.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010024
Darin Petkov5eb05422012-05-11 15:45:25 +020025using std::string;
Darin Petkov79d74c92012-03-07 17:20:32 +010026using testing::_;
Alex Deymofddc09a2013-07-03 18:41:31 -070027using testing::Mock;
Darin Petkovf3c71d72012-03-21 12:32:15 +010028using testing::NiceMock;
29using testing::Return;
Darin Petkov5eb05422012-05-11 15:45:25 +020030using testing::ReturnRef;
Darin Petkov79d74c92012-03-07 17:20:32 +010031
Darin Petkov33af05c2012-02-28 10:10:30 +010032namespace shill {
33
34class VPNServiceTest : public testing::Test {
35 public:
36 VPNServiceTest()
Darin Petkov5eb05422012-05-11 15:45:25 +020037 : interface_name_("test-interface"),
38 driver_(new MockVPNDriver()),
Darin Petkova0e645e2012-04-25 11:38:59 +020039 manager_(&control_, NULL, NULL, NULL),
Thieu Le6c1e3bb2013-02-06 15:20:35 -080040 metrics_(NULL),
Darin Petkov5eb05422012-05-11 15:45:25 +020041 device_info_(&control_, NULL, NULL, NULL),
42 connection_(new NiceMock<MockConnection>(&device_info_)),
43 sockets_(new MockSockets()),
Darin Petkova0e645e2012-04-25 11:38:59 +020044 service_(new VPNService(&control_, NULL, &metrics_, &manager_,
Darin Petkov5eb05422012-05-11 15:45:25 +020045 driver_)) {
46 service_->sockets_.reset(sockets_); // Passes ownership.
47 }
Darin Petkov33af05c2012-02-28 10:10:30 +010048
49 virtual ~VPNServiceTest() {}
50
51 protected:
Darin Petkov5eb05422012-05-11 15:45:25 +020052 virtual void SetUp() {
53 ON_CALL(*connection_, interface_name())
54 .WillByDefault(ReturnRef(interface_name_));
Paul Stewart1e3bc4962012-09-14 12:20:22 -070055 ON_CALL(*connection_, ipconfig_rpc_identifier())
56 .WillByDefault(ReturnRef(ipconfig_rpc_identifier_));
Darin Petkov5eb05422012-05-11 15:45:25 +020057 }
58
59 virtual void TearDown() {
60 EXPECT_CALL(device_info_, FlushAddresses(0));
61 }
62
63 void SetServiceState(Service::ConnectState state) {
64 service_->state_ = state;
65 }
66
Darin Petkov79349f02013-01-24 16:18:26 +010067 void SetHasEverConnected(bool connected) {
68 service_->has_ever_connected_ = connected;
69 }
70
71 void SetConnectable(bool connectable) {
72 service_->connectable_ = connectable;
73 }
74
Darin Petkov4cbff5b2013-01-29 16:29:05 +010075 const char *GetAutoConnOffline() {
76 return Service::kAutoConnOffline;
77 }
78
79 const char *GetAutoConnNeverConnected() {
80 return VPNService::kAutoConnNeverConnected;
81 }
82
83 const char *GetAutoConnVPNAlreadyActive() {
84 return VPNService::kAutoConnVPNAlreadyActive;
85 }
86
87 bool IsAutoConnectable(const char **reason) const {
88 return service_->IsAutoConnectable(reason);
89 }
90
Darin Petkovc3505a52013-03-18 15:13:29 +010091 // Takes ownership of |provider|.
92 void SetVPNProvider(VPNProvider *provider) {
93 manager_.vpn_provider_.reset(provider);
94 }
95
mukesh agrawalcbfb34e2013-04-17 19:33:25 -070096 ServiceMockAdaptor *GetAdaptor() {
97 return dynamic_cast<ServiceMockAdaptor *>(service_->adaptor());
98 }
99
Darin Petkov5eb05422012-05-11 15:45:25 +0200100 std::string interface_name_;
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700101 std::string ipconfig_rpc_identifier_;
Darin Petkov33af05c2012-02-28 10:10:30 +0100102 MockVPNDriver *driver_; // Owned by |service_|.
103 NiceMockControl control_;
Darin Petkova0e645e2012-04-25 11:38:59 +0200104 MockManager manager_;
Darin Petkov33af05c2012-02-28 10:10:30 +0100105 MockMetrics metrics_;
Darin Petkov5eb05422012-05-11 15:45:25 +0200106 MockDeviceInfo device_info_;
107 scoped_refptr<NiceMock<MockConnection> > connection_;
108 MockSockets *sockets_; // Owned by |service_|.
Darin Petkov33af05c2012-02-28 10:10:30 +0100109 VPNServiceRefPtr service_;
110};
111
112TEST_F(VPNServiceTest, Connect) {
Darin Petkov2f903b32012-04-18 12:56:43 +0200113 EXPECT_TRUE(service_->connectable());
Darin Petkov33af05c2012-02-28 10:10:30 +0100114 Error error;
Darin Petkov79d74c92012-03-07 17:20:32 +0100115 EXPECT_CALL(*driver_, Connect(_, &error));
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700116 service_->Connect(&error, "in test");
Darin Petkov79d74c92012-03-07 17:20:32 +0100117 EXPECT_TRUE(error.IsSuccess());
Darin Petkov33af05c2012-02-28 10:10:30 +0100118}
119
Darin Petkov2f903b32012-04-18 12:56:43 +0200120TEST_F(VPNServiceTest, ConnectAlreadyConnected) {
121 Error error;
122 EXPECT_CALL(*driver_, Connect(_, _)).Times(0);
Darin Petkov5eb05422012-05-11 15:45:25 +0200123 SetServiceState(Service::kStateOnline);
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700124 service_->Connect(&error, "in test");
Darin Petkov2f903b32012-04-18 12:56:43 +0200125 EXPECT_EQ(Error::kAlreadyConnected, error.type());
126 error.Reset();
Darin Petkov5eb05422012-05-11 15:45:25 +0200127 SetServiceState(Service::kStateConfiguring);
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700128 service_->Connect(&error, "in test");
mukesh agrawaldba10462013-06-04 11:36:21 -0700129 EXPECT_EQ(Error::kInProgress, error.type());
Darin Petkov2f903b32012-04-18 12:56:43 +0200130}
131
Darin Petkov6aa21872012-03-09 16:10:19 +0100132TEST_F(VPNServiceTest, Disconnect) {
133 Error error;
134 EXPECT_CALL(*driver_, Disconnect());
135 service_->Disconnect(&error);
136 EXPECT_TRUE(error.IsSuccess());
137}
138
Darin Petkov02867712012-03-12 14:25:05 +0100139TEST_F(VPNServiceTest, CreateStorageIdentifierNoHost) {
140 KeyValueStore args;
141 Error error;
Darin Petkov4e02ba22013-04-02 13:44:08 +0200142 args.SetString(flimflam::kNameProperty, "vpn-name");
Darin Petkov02867712012-03-12 14:25:05 +0100143 EXPECT_EQ("", VPNService::CreateStorageIdentifier(args, &error));
144 EXPECT_EQ(Error::kInvalidProperty, error.type());
145}
146
147TEST_F(VPNServiceTest, CreateStorageIdentifierNoName) {
148 KeyValueStore args;
149 Error error;
150 args.SetString(flimflam::kProviderHostProperty, "10.8.0.1");
151 EXPECT_EQ("", VPNService::CreateStorageIdentifier(args, &error));
152 EXPECT_EQ(Error::kNotSupported, error.type());
153}
154
155TEST_F(VPNServiceTest, CreateStorageIdentifier) {
156 KeyValueStore args;
157 Error error;
Darin Petkov4e02ba22013-04-02 13:44:08 +0200158 args.SetString(flimflam::kNameProperty, "vpn-name");
Darin Petkov02867712012-03-12 14:25:05 +0100159 args.SetString(flimflam::kProviderHostProperty, "10.8.0.1");
160 EXPECT_EQ("vpn_10_8_0_1_vpn_name",
161 VPNService::CreateStorageIdentifier(args, &error));
162 EXPECT_TRUE(error.IsSuccess());
163}
164
Darin Petkov33af05c2012-02-28 10:10:30 +0100165TEST_F(VPNServiceTest, GetStorageIdentifier) {
166 EXPECT_EQ("", service_->GetStorageIdentifier());
Darin Petkov02867712012-03-12 14:25:05 +0100167 service_->set_storage_id("foo");
168 EXPECT_EQ("foo", service_->GetStorageIdentifier());
Darin Petkov33af05c2012-02-28 10:10:30 +0100169}
170
171TEST_F(VPNServiceTest, GetDeviceRpcId) {
172 Error error;
173 EXPECT_EQ("/", service_->GetDeviceRpcId(&error));
174 EXPECT_EQ(Error::kNotSupported, error.type());
175}
176
Darin Petkovf3c71d72012-03-21 12:32:15 +0100177TEST_F(VPNServiceTest, Load) {
178 NiceMock<MockStore> storage;
179 static const char kStorageID[] = "storage-id";
180 service_->set_storage_id(kStorageID);
181 EXPECT_CALL(storage, ContainsGroup(kStorageID)).WillOnce(Return(true));
Darin Petkovcb715292012-04-25 13:04:37 +0200182 EXPECT_CALL(*driver_, Load(&storage, kStorageID))
183 .WillOnce(Return(true));
Darin Petkovf3c71d72012-03-21 12:32:15 +0100184 EXPECT_TRUE(service_->Load(&storage));
185}
186
187TEST_F(VPNServiceTest, Save) {
188 NiceMock<MockStore> storage;
189 static const char kStorageID[] = "storage-id";
190 service_->set_storage_id(kStorageID);
Darin Petkovcb715292012-04-25 13:04:37 +0200191 EXPECT_CALL(*driver_, Save(&storage, kStorageID, false))
192 .WillOnce(Return(true));
Darin Petkovf3c71d72012-03-21 12:32:15 +0100193 EXPECT_TRUE(service_->Save(&storage));
194}
195
Darin Petkovcb715292012-04-25 13:04:37 +0200196TEST_F(VPNServiceTest, SaveCredentials) {
197 NiceMock<MockStore> storage;
198 static const char kStorageID[] = "storage-id";
199 service_->set_storage_id(kStorageID);
200 service_->set_save_credentials(true);
201 EXPECT_CALL(*driver_, Save(&storage, kStorageID, true))
202 .WillOnce(Return(true));
203 EXPECT_TRUE(service_->Save(&storage));
204}
205
206TEST_F(VPNServiceTest, Unload) {
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700207 service_->SetAutoConnect(true);
Darin Petkovcb715292012-04-25 13:04:37 +0200208 service_->set_save_credentials(true);
209 EXPECT_CALL(*driver_, Disconnect());
210 EXPECT_CALL(*driver_, UnloadCredentials());
Darin Petkovc3505a52013-03-18 15:13:29 +0100211 MockVPNProvider *provider = new MockVPNProvider;
212 SetVPNProvider(provider);
213 provider->services_.push_back(service_);
Darin Petkovcb715292012-04-25 13:04:37 +0200214 service_->Unload();
215 EXPECT_FALSE(service_->auto_connect());
216 EXPECT_FALSE(service_->save_credentials());
Darin Petkovc3505a52013-03-18 15:13:29 +0100217 EXPECT_TRUE(provider->services_.empty());
Darin Petkovcb715292012-04-25 13:04:37 +0200218}
219
Paul Stewartebd38562012-03-23 13:06:40 -0700220TEST_F(VPNServiceTest, InitPropertyStore) {
221 EXPECT_CALL(*driver_, InitPropertyStore(service_->mutable_store()));
222 service_->InitDriverPropertyStore();
223}
224
Darin Petkov1d0080a2012-04-30 17:10:36 +0200225TEST_F(VPNServiceTest, MakeFavorite) {
226 EXPECT_FALSE(service_->favorite());
227 EXPECT_FALSE(service_->auto_connect());
228 service_->MakeFavorite();
229 EXPECT_TRUE(service_->favorite());
230 EXPECT_FALSE(service_->auto_connect());
231}
232
Darin Petkov5eb05422012-05-11 15:45:25 +0200233TEST_F(VPNServiceTest, SetConnection) {
234 EXPECT_FALSE(service_->connection_binder_.get());
235 EXPECT_FALSE(service_->connection());
236 EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
237 service_->SetConnection(connection_);
238 ASSERT_TRUE(service_->connection_binder_.get());
239 EXPECT_EQ(connection_.get(),
240 service_->connection_binder_->connection().get());
241 EXPECT_EQ(connection_.get(), service_->connection().get());
242 EXPECT_CALL(*driver_, OnConnectionDisconnected()).Times(0);
243}
244
245TEST_F(VPNServiceTest, OnConnectionDisconnected) {
246 EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
247 service_->SetConnection(connection_);
248 EXPECT_CALL(*driver_, OnConnectionDisconnected()).Times(1);
249 connection_->OnLowerDisconnect();
250}
251
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100252TEST_F(VPNServiceTest, IsAutoConnectableOffline) {
253 EXPECT_TRUE(service_->connectable());
254 const char *reason = NULL;
255 EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(false));
256 EXPECT_FALSE(IsAutoConnectable(&reason));
257 EXPECT_STREQ(GetAutoConnOffline(), reason);
258}
259
260TEST_F(VPNServiceTest, IsAutoConnectableNeverConnected) {
Darin Petkov79349f02013-01-24 16:18:26 +0100261 EXPECT_TRUE(service_->connectable());
262 EXPECT_FALSE(service_->has_ever_connected());
Darin Petkov79349f02013-01-24 16:18:26 +0100263 const char *reason = NULL;
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100264 EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(true));
265 EXPECT_FALSE(IsAutoConnectable(&reason));
266 EXPECT_STREQ(GetAutoConnNeverConnected(), reason);
267}
Darin Petkov79349f02013-01-24 16:18:26 +0100268
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100269TEST_F(VPNServiceTest, IsAutoConnectableVPNAlreadyActive) {
270 EXPECT_TRUE(service_->connectable());
Darin Petkov79349f02013-01-24 16:18:26 +0100271 SetHasEverConnected(true);
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100272 EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(true));
Darin Petkovc3505a52013-03-18 15:13:29 +0100273 MockVPNProvider *provider = new MockVPNProvider;
274 SetVPNProvider(provider);
275 EXPECT_CALL(*provider, HasActiveService()).WillOnce(Return(true));
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100276 const char *reason = NULL;
277 EXPECT_FALSE(IsAutoConnectable(&reason));
278 EXPECT_STREQ(GetAutoConnVPNAlreadyActive(), reason);
279}
Darin Petkov79349f02013-01-24 16:18:26 +0100280
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100281TEST_F(VPNServiceTest, IsAutoConnectableNotConnectable) {
282 const char *reason = NULL;
Darin Petkov79349f02013-01-24 16:18:26 +0100283 SetConnectable(false);
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100284 EXPECT_FALSE(IsAutoConnectable(&reason));
285}
286
287TEST_F(VPNServiceTest, IsAutoConnectable) {
288 EXPECT_TRUE(service_->connectable());
289 SetHasEverConnected(true);
290 EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(true));
Darin Petkovc3505a52013-03-18 15:13:29 +0100291 MockVPNProvider *provider = new MockVPNProvider;
292 SetVPNProvider(provider);
293 EXPECT_CALL(*provider, HasActiveService()).WillOnce(Return(false));
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100294 const char *reason = NULL;
295 EXPECT_TRUE(IsAutoConnectable(&reason));
296 EXPECT_FALSE(reason);
Darin Petkov79349f02013-01-24 16:18:26 +0100297}
298
Darin Petkov9c6e9812013-03-26 13:49:07 +0100299TEST_F(VPNServiceTest, SetNamePropertyTrivial) {
300 DBus::Error error;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700301 // A null change returns false, but with error set to success.
302 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
303 flimflam::kNameProperty,
304 DBusAdaptor::StringToVariant(
305 service_->friendly_name()),
306 &error));
307 EXPECT_FALSE(error.is_set());
Darin Petkov9c6e9812013-03-26 13:49:07 +0100308}
309
310TEST_F(VPNServiceTest, SetNameProperty) {
311 const string kHost = "1.2.3.4";
312 driver_->args()->SetString(flimflam::kProviderHostProperty, kHost);
313 string kOldId = service_->GetStorageIdentifier();
314 DBus::Error error;
315 const string kName = "New Name";
316 scoped_refptr<MockProfile> profile(
317 new MockProfile(&control_, &metrics_, &manager_));
318 EXPECT_CALL(*profile, DeleteEntry(kOldId, _));
319 EXPECT_CALL(*profile, UpdateService(_));
320 service_->set_profile(profile);
321 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
322 flimflam::kNameProperty,
323 DBusAdaptor::StringToVariant(kName),
324 &error));
325 EXPECT_NE(service_->GetStorageIdentifier(), kOldId);
326 EXPECT_EQ(kName, service_->friendly_name());
327}
328
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700329TEST_F(VPNServiceTest, PropertyChanges) {
330 TestCommonPropertyChanges(service_, GetAdaptor());
331 TestAutoConnectPropertyChange(service_, GetAdaptor());
332
333 const string kHost = "1.2.3.4";
334 scoped_refptr<MockProfile> profile(
335 new NiceMock<MockProfile>(&control_, &metrics_, &manager_));
336 service_->set_profile(profile);
337 driver_->args()->SetString(flimflam::kProviderHostProperty, kHost);
338 TestNamePropertyChange(service_, GetAdaptor());
339}
340
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700341// Custom property setters should return false, and make no changes, if
342// the new value is the same as the old value.
343TEST_F(VPNServiceTest, CustomSetterNoopChange) {
344 TestCustomSetterNoopChange(service_, &manager_);
345}
346
Alex Deymofddc09a2013-07-03 18:41:31 -0700347TEST_F(VPNServiceTest, GetPhysicalTechologyPropertyFailsIfNoCarrier) {
348 scoped_refptr<Connection> null_connection;
349
350 EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
351 service_->SetConnection(connection_);
352 EXPECT_EQ(connection_.get(), service_->connection().get());
353
354 // Simulate an error in the GetCarrierConnection() returning a NULL reference.
355 EXPECT_CALL(*connection_, GetCarrierConnection())
356 .WillOnce(Return(null_connection));
357
358 Error error;
359 EXPECT_EQ("", service_->GetPhysicalTechologyProperty(&error));
360 EXPECT_EQ(Error::kOperationFailed, error.type());
361}
362
363TEST_F(VPNServiceTest, GetPhysicalTechologyPropertyOverWifi) {
364 scoped_refptr<NiceMock<MockConnection>> lower_connection_ =
365 new NiceMock<MockConnection>(&device_info_);
366
367 EXPECT_CALL(*connection_, technology())
368 .Times(0);
369 EXPECT_CALL(*connection_, GetCarrierConnection())
370 .WillOnce(Return(lower_connection_));
371
372 EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
373 service_->SetConnection(connection_);
374 EXPECT_EQ(connection_.get(), service_->connection().get());
375
376 // Set the type of the lower connection to "wifi" and expect that type to be
377 // returned by GetPhysical TechnologyProperty().
378 EXPECT_CALL(*lower_connection_, technology())
379 .WillOnce(Return(Technology::kWifi));
380
381 Error error;
382 EXPECT_EQ(flimflam::kTypeWifi,
383 service_->GetPhysicalTechologyProperty(&error));
384 EXPECT_TRUE(error.IsSuccess());
385
386 // Clear expectations now, so the Return(lower_connection_) action releases
387 // the reference to |lower_connection_| allowing it to be destroyed now.
388 Mock::VerifyAndClearExpectations(connection_);
389 // Destroying the |lower_connection_| at function exit will also call an extra
390 // FlushAddresses on the |device_info_| object.
391 EXPECT_CALL(device_info_, FlushAddresses(0));
392}
393
Darin Petkov33af05c2012-02-28 10:10:30 +0100394} // namespace shill