blob: beec2fb11c911a7fa5809668e967d6e2783b042a [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);
Paul Stewartb87d22b2013-07-29 11:11:37 -070094 manager_.UpdateProviderMapping();
Darin Petkovc3505a52013-03-18 15:13:29 +010095 }
96
mukesh agrawalcbfb34e2013-04-17 19:33:25 -070097 ServiceMockAdaptor *GetAdaptor() {
98 return dynamic_cast<ServiceMockAdaptor *>(service_->adaptor());
99 }
100
Darin Petkov5eb05422012-05-11 15:45:25 +0200101 std::string interface_name_;
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700102 std::string ipconfig_rpc_identifier_;
Darin Petkov33af05c2012-02-28 10:10:30 +0100103 MockVPNDriver *driver_; // Owned by |service_|.
104 NiceMockControl control_;
Darin Petkova0e645e2012-04-25 11:38:59 +0200105 MockManager manager_;
Darin Petkov33af05c2012-02-28 10:10:30 +0100106 MockMetrics metrics_;
Darin Petkov5eb05422012-05-11 15:45:25 +0200107 MockDeviceInfo device_info_;
108 scoped_refptr<NiceMock<MockConnection> > connection_;
109 MockSockets *sockets_; // Owned by |service_|.
Darin Petkov33af05c2012-02-28 10:10:30 +0100110 VPNServiceRefPtr service_;
111};
112
113TEST_F(VPNServiceTest, Connect) {
Darin Petkov2f903b32012-04-18 12:56:43 +0200114 EXPECT_TRUE(service_->connectable());
Darin Petkov33af05c2012-02-28 10:10:30 +0100115 Error error;
Darin Petkov79d74c92012-03-07 17:20:32 +0100116 EXPECT_CALL(*driver_, Connect(_, &error));
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700117 service_->Connect(&error, "in test");
Darin Petkov79d74c92012-03-07 17:20:32 +0100118 EXPECT_TRUE(error.IsSuccess());
Darin Petkov33af05c2012-02-28 10:10:30 +0100119}
120
Darin Petkov2f903b32012-04-18 12:56:43 +0200121TEST_F(VPNServiceTest, ConnectAlreadyConnected) {
122 Error error;
123 EXPECT_CALL(*driver_, Connect(_, _)).Times(0);
Darin Petkov5eb05422012-05-11 15:45:25 +0200124 SetServiceState(Service::kStateOnline);
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700125 service_->Connect(&error, "in test");
Darin Petkov2f903b32012-04-18 12:56:43 +0200126 EXPECT_EQ(Error::kAlreadyConnected, error.type());
127 error.Reset();
Darin Petkov5eb05422012-05-11 15:45:25 +0200128 SetServiceState(Service::kStateConfiguring);
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700129 service_->Connect(&error, "in test");
mukesh agrawaldba10462013-06-04 11:36:21 -0700130 EXPECT_EQ(Error::kInProgress, error.type());
Darin Petkov2f903b32012-04-18 12:56:43 +0200131}
132
Darin Petkov6aa21872012-03-09 16:10:19 +0100133TEST_F(VPNServiceTest, Disconnect) {
134 Error error;
135 EXPECT_CALL(*driver_, Disconnect());
136 service_->Disconnect(&error);
137 EXPECT_TRUE(error.IsSuccess());
138}
139
Darin Petkov02867712012-03-12 14:25:05 +0100140TEST_F(VPNServiceTest, CreateStorageIdentifierNoHost) {
141 KeyValueStore args;
142 Error error;
Ben Chan73728782013-09-20 13:40:54 -0700143 args.SetString(kNameProperty, "vpn-name");
Darin Petkov02867712012-03-12 14:25:05 +0100144 EXPECT_EQ("", VPNService::CreateStorageIdentifier(args, &error));
145 EXPECT_EQ(Error::kInvalidProperty, error.type());
146}
147
148TEST_F(VPNServiceTest, CreateStorageIdentifierNoName) {
149 KeyValueStore args;
150 Error error;
Ben Chan73728782013-09-20 13:40:54 -0700151 args.SetString(kProviderHostProperty, "10.8.0.1");
Darin Petkov02867712012-03-12 14:25:05 +0100152 EXPECT_EQ("", VPNService::CreateStorageIdentifier(args, &error));
153 EXPECT_EQ(Error::kNotSupported, error.type());
154}
155
156TEST_F(VPNServiceTest, CreateStorageIdentifier) {
157 KeyValueStore args;
158 Error error;
Ben Chan73728782013-09-20 13:40:54 -0700159 args.SetString(kNameProperty, "vpn-name");
160 args.SetString(kProviderHostProperty, "10.8.0.1");
Darin Petkov02867712012-03-12 14:25:05 +0100161 EXPECT_EQ("vpn_10_8_0_1_vpn_name",
162 VPNService::CreateStorageIdentifier(args, &error));
163 EXPECT_TRUE(error.IsSuccess());
164}
165
Darin Petkov33af05c2012-02-28 10:10:30 +0100166TEST_F(VPNServiceTest, GetStorageIdentifier) {
167 EXPECT_EQ("", service_->GetStorageIdentifier());
Darin Petkov02867712012-03-12 14:25:05 +0100168 service_->set_storage_id("foo");
169 EXPECT_EQ("foo", service_->GetStorageIdentifier());
Darin Petkov33af05c2012-02-28 10:10:30 +0100170}
171
172TEST_F(VPNServiceTest, GetDeviceRpcId) {
173 Error error;
174 EXPECT_EQ("/", service_->GetDeviceRpcId(&error));
175 EXPECT_EQ(Error::kNotSupported, error.type());
176}
177
Darin Petkovf3c71d72012-03-21 12:32:15 +0100178TEST_F(VPNServiceTest, Load) {
179 NiceMock<MockStore> storage;
180 static const char kStorageID[] = "storage-id";
181 service_->set_storage_id(kStorageID);
182 EXPECT_CALL(storage, ContainsGroup(kStorageID)).WillOnce(Return(true));
Darin Petkovcb715292012-04-25 13:04:37 +0200183 EXPECT_CALL(*driver_, Load(&storage, kStorageID))
184 .WillOnce(Return(true));
Darin Petkovf3c71d72012-03-21 12:32:15 +0100185 EXPECT_TRUE(service_->Load(&storage));
186}
187
188TEST_F(VPNServiceTest, Save) {
189 NiceMock<MockStore> storage;
190 static const char kStorageID[] = "storage-id";
191 service_->set_storage_id(kStorageID);
Darin Petkovcb715292012-04-25 13:04:37 +0200192 EXPECT_CALL(*driver_, Save(&storage, kStorageID, false))
193 .WillOnce(Return(true));
Darin Petkovf3c71d72012-03-21 12:32:15 +0100194 EXPECT_TRUE(service_->Save(&storage));
195}
196
Darin Petkovcb715292012-04-25 13:04:37 +0200197TEST_F(VPNServiceTest, SaveCredentials) {
198 NiceMock<MockStore> storage;
199 static const char kStorageID[] = "storage-id";
200 service_->set_storage_id(kStorageID);
201 service_->set_save_credentials(true);
202 EXPECT_CALL(*driver_, Save(&storage, kStorageID, true))
203 .WillOnce(Return(true));
204 EXPECT_TRUE(service_->Save(&storage));
205}
206
207TEST_F(VPNServiceTest, Unload) {
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700208 service_->SetAutoConnect(true);
Darin Petkovcb715292012-04-25 13:04:37 +0200209 service_->set_save_credentials(true);
210 EXPECT_CALL(*driver_, Disconnect());
211 EXPECT_CALL(*driver_, UnloadCredentials());
Darin Petkovc3505a52013-03-18 15:13:29 +0100212 MockVPNProvider *provider = new MockVPNProvider;
213 SetVPNProvider(provider);
214 provider->services_.push_back(service_);
Darin Petkovcb715292012-04-25 13:04:37 +0200215 service_->Unload();
216 EXPECT_FALSE(service_->auto_connect());
217 EXPECT_FALSE(service_->save_credentials());
Darin Petkovc3505a52013-03-18 15:13:29 +0100218 EXPECT_TRUE(provider->services_.empty());
Darin Petkovcb715292012-04-25 13:04:37 +0200219}
220
Paul Stewartebd38562012-03-23 13:06:40 -0700221TEST_F(VPNServiceTest, InitPropertyStore) {
222 EXPECT_CALL(*driver_, InitPropertyStore(service_->mutable_store()));
223 service_->InitDriverPropertyStore();
224}
225
Paul Stewart2da34c02013-10-17 15:28:56 -0700226TEST_F(VPNServiceTest, EnableAndRetainAutoConnect) {
227 EXPECT_FALSE(service_->retain_auto_connect());
Darin Petkov1d0080a2012-04-30 17:10:36 +0200228 EXPECT_FALSE(service_->auto_connect());
Paul Stewart2da34c02013-10-17 15:28:56 -0700229 service_->EnableAndRetainAutoConnect();
230 EXPECT_TRUE(service_->retain_auto_connect());
Darin Petkov1d0080a2012-04-30 17:10:36 +0200231 EXPECT_FALSE(service_->auto_connect());
232}
233
Darin Petkov5eb05422012-05-11 15:45:25 +0200234TEST_F(VPNServiceTest, SetConnection) {
235 EXPECT_FALSE(service_->connection_binder_.get());
236 EXPECT_FALSE(service_->connection());
237 EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
238 service_->SetConnection(connection_);
239 ASSERT_TRUE(service_->connection_binder_.get());
240 EXPECT_EQ(connection_.get(),
241 service_->connection_binder_->connection().get());
242 EXPECT_EQ(connection_.get(), service_->connection().get());
243 EXPECT_CALL(*driver_, OnConnectionDisconnected()).Times(0);
244}
245
246TEST_F(VPNServiceTest, OnConnectionDisconnected) {
247 EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
248 service_->SetConnection(connection_);
249 EXPECT_CALL(*driver_, OnConnectionDisconnected()).Times(1);
250 connection_->OnLowerDisconnect();
251}
252
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100253TEST_F(VPNServiceTest, IsAutoConnectableOffline) {
254 EXPECT_TRUE(service_->connectable());
255 const char *reason = NULL;
256 EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(false));
257 EXPECT_FALSE(IsAutoConnectable(&reason));
258 EXPECT_STREQ(GetAutoConnOffline(), reason);
259}
260
261TEST_F(VPNServiceTest, IsAutoConnectableNeverConnected) {
Darin Petkov79349f02013-01-24 16:18:26 +0100262 EXPECT_TRUE(service_->connectable());
263 EXPECT_FALSE(service_->has_ever_connected());
Darin Petkov79349f02013-01-24 16:18:26 +0100264 const char *reason = NULL;
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100265 EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(true));
266 EXPECT_FALSE(IsAutoConnectable(&reason));
267 EXPECT_STREQ(GetAutoConnNeverConnected(), reason);
268}
Darin Petkov79349f02013-01-24 16:18:26 +0100269
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100270TEST_F(VPNServiceTest, IsAutoConnectableVPNAlreadyActive) {
271 EXPECT_TRUE(service_->connectable());
Darin Petkov79349f02013-01-24 16:18:26 +0100272 SetHasEverConnected(true);
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100273 EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(true));
Darin Petkovc3505a52013-03-18 15:13:29 +0100274 MockVPNProvider *provider = new MockVPNProvider;
275 SetVPNProvider(provider);
276 EXPECT_CALL(*provider, HasActiveService()).WillOnce(Return(true));
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100277 const char *reason = NULL;
278 EXPECT_FALSE(IsAutoConnectable(&reason));
279 EXPECT_STREQ(GetAutoConnVPNAlreadyActive(), reason);
280}
Darin Petkov79349f02013-01-24 16:18:26 +0100281
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100282TEST_F(VPNServiceTest, IsAutoConnectableNotConnectable) {
283 const char *reason = NULL;
Darin Petkov79349f02013-01-24 16:18:26 +0100284 SetConnectable(false);
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100285 EXPECT_FALSE(IsAutoConnectable(&reason));
286}
287
288TEST_F(VPNServiceTest, IsAutoConnectable) {
289 EXPECT_TRUE(service_->connectable());
290 SetHasEverConnected(true);
291 EXPECT_CALL(manager_, IsOnline()).WillOnce(Return(true));
Darin Petkovc3505a52013-03-18 15:13:29 +0100292 MockVPNProvider *provider = new MockVPNProvider;
293 SetVPNProvider(provider);
294 EXPECT_CALL(*provider, HasActiveService()).WillOnce(Return(false));
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100295 const char *reason = NULL;
296 EXPECT_TRUE(IsAutoConnectable(&reason));
297 EXPECT_FALSE(reason);
Darin Petkov79349f02013-01-24 16:18:26 +0100298}
299
Darin Petkov9c6e9812013-03-26 13:49:07 +0100300TEST_F(VPNServiceTest, SetNamePropertyTrivial) {
301 DBus::Error error;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700302 // A null change returns false, but with error set to success.
303 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
Ben Chan73728782013-09-20 13:40:54 -0700304 kNameProperty,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700305 DBusAdaptor::StringToVariant(
306 service_->friendly_name()),
307 &error));
308 EXPECT_FALSE(error.is_set());
Darin Petkov9c6e9812013-03-26 13:49:07 +0100309}
310
311TEST_F(VPNServiceTest, SetNameProperty) {
312 const string kHost = "1.2.3.4";
Ben Chan73728782013-09-20 13:40:54 -0700313 driver_->args()->SetString(kProviderHostProperty, kHost);
Darin Petkov9c6e9812013-03-26 13:49:07 +0100314 string kOldId = service_->GetStorageIdentifier();
315 DBus::Error error;
316 const string kName = "New Name";
317 scoped_refptr<MockProfile> profile(
318 new MockProfile(&control_, &metrics_, &manager_));
319 EXPECT_CALL(*profile, DeleteEntry(kOldId, _));
320 EXPECT_CALL(*profile, UpdateService(_));
321 service_->set_profile(profile);
322 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
Ben Chan73728782013-09-20 13:40:54 -0700323 kNameProperty,
Darin Petkov9c6e9812013-03-26 13:49:07 +0100324 DBusAdaptor::StringToVariant(kName),
325 &error));
326 EXPECT_NE(service_->GetStorageIdentifier(), kOldId);
327 EXPECT_EQ(kName, service_->friendly_name());
328}
329
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700330TEST_F(VPNServiceTest, PropertyChanges) {
331 TestCommonPropertyChanges(service_, GetAdaptor());
332 TestAutoConnectPropertyChange(service_, GetAdaptor());
333
334 const string kHost = "1.2.3.4";
335 scoped_refptr<MockProfile> profile(
336 new NiceMock<MockProfile>(&control_, &metrics_, &manager_));
337 service_->set_profile(profile);
Ben Chan73728782013-09-20 13:40:54 -0700338 driver_->args()->SetString(kProviderHostProperty, kHost);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700339 TestNamePropertyChange(service_, GetAdaptor());
340}
341
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700342// Custom property setters should return false, and make no changes, if
343// the new value is the same as the old value.
344TEST_F(VPNServiceTest, CustomSetterNoopChange) {
345 TestCustomSetterNoopChange(service_, &manager_);
346}
347
Alex Deymofddc09a2013-07-03 18:41:31 -0700348TEST_F(VPNServiceTest, GetPhysicalTechologyPropertyFailsIfNoCarrier) {
349 scoped_refptr<Connection> null_connection;
350
351 EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
352 service_->SetConnection(connection_);
353 EXPECT_EQ(connection_.get(), service_->connection().get());
354
355 // Simulate an error in the GetCarrierConnection() returning a NULL reference.
356 EXPECT_CALL(*connection_, GetCarrierConnection())
357 .WillOnce(Return(null_connection));
358
359 Error error;
360 EXPECT_EQ("", service_->GetPhysicalTechologyProperty(&error));
361 EXPECT_EQ(Error::kOperationFailed, error.type());
362}
363
364TEST_F(VPNServiceTest, GetPhysicalTechologyPropertyOverWifi) {
365 scoped_refptr<NiceMock<MockConnection>> lower_connection_ =
366 new NiceMock<MockConnection>(&device_info_);
367
368 EXPECT_CALL(*connection_, technology())
369 .Times(0);
370 EXPECT_CALL(*connection_, GetCarrierConnection())
371 .WillOnce(Return(lower_connection_));
372
373 EXPECT_CALL(*sockets_, Socket(_, _, _)).WillOnce(Return(-1));
374 service_->SetConnection(connection_);
375 EXPECT_EQ(connection_.get(), service_->connection().get());
376
377 // Set the type of the lower connection to "wifi" and expect that type to be
378 // returned by GetPhysical TechnologyProperty().
379 EXPECT_CALL(*lower_connection_, technology())
380 .WillOnce(Return(Technology::kWifi));
381
382 Error error;
Ben Chan73728782013-09-20 13:40:54 -0700383 EXPECT_EQ(kTypeWifi, service_->GetPhysicalTechologyProperty(&error));
Alex Deymofddc09a2013-07-03 18:41:31 -0700384 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