blob: 00d12b3471a794b25880dc31e8f8f8b59f2639b7 [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_provider.h"
6
7#include <chromeos/dbus/service_constants.h>
8#include <gtest/gtest.h>
9
10#include "shill/error.h"
11#include "shill/nice_mock_control.h"
12#include "shill/mock_adaptors.h"
Darin Petkov79d74c92012-03-07 17:20:32 +010013#include "shill/mock_device_info.h"
Paul Stewartca6abd42012-03-01 15:45:29 -080014#include "shill/mock_manager.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010015#include "shill/mock_metrics.h"
Paul Stewart66815332012-04-09 18:09:36 -070016#include "shill/mock_profile.h"
17#include "shill/mock_store.h"
Paul Stewartca6abd42012-03-01 15:45:29 -080018#include "shill/mock_vpn_driver.h"
Paul Stewart65512e12012-03-26 18:01:08 -070019#include "shill/mock_vpn_service.h"
Darin Petkov33af05c2012-02-28 10:10:30 +010020
Paul Stewartca6abd42012-03-01 15:45:29 -080021using std::string;
22using testing::_;
Paul Stewart66815332012-04-09 18:09:36 -070023using testing::DoAll;
24using testing::NiceMock;
Paul Stewartca6abd42012-03-01 15:45:29 -080025using testing::Return;
Paul Stewart66815332012-04-09 18:09:36 -070026using testing::SetArgumentPointee;
Paul Stewartca6abd42012-03-01 15:45:29 -080027
Darin Petkov33af05c2012-02-28 10:10:30 +010028namespace shill {
29
30class VPNProviderTest : public testing::Test {
31 public:
32 VPNProviderTest()
Thieu Le6c1e3bb2013-02-06 15:20:35 -080033 : metrics_(NULL),
34 manager_(&control_, NULL, &metrics_, NULL),
Darin Petkov79d74c92012-03-07 17:20:32 +010035 device_info_(&control_, NULL, &metrics_, &manager_),
Paul Stewartca6abd42012-03-01 15:45:29 -080036 provider_(&control_, NULL, &metrics_, &manager_) {}
Darin Petkov33af05c2012-02-28 10:10:30 +010037
38 virtual ~VPNProviderTest() {}
39
40 protected:
Darin Petkov02867712012-03-12 14:25:05 +010041 static const char kHost[];
42 static const char kName[];
43
Darin Petkov457728b2013-01-09 09:49:08 +010044 string GetServiceFriendlyName(const ServiceRefPtr &service) {
45 return service->friendly_name();
46 }
47
Darin Petkov4cbff5b2013-01-29 16:29:05 +010048 void SetConnectState(const ServiceRefPtr &service,
49 Service::ConnectState state) {
50 service->state_ = state;
51 }
52
53 void AddService(const VPNServiceRefPtr &service) {
54 provider_.services_.push_back(service);
55 }
56
Darin Petkov9c6e9812013-03-26 13:49:07 +010057 VPNServiceRefPtr GetServiceAt(int idx) {
58 return provider_.services_[idx];
59 }
60
Paul Stewartbc14fb72013-07-30 08:21:58 -070061 size_t GetServiceCount() const {
62 return provider_.services_.size();
63 }
64
Darin Petkov33af05c2012-02-28 10:10:30 +010065 NiceMockControl control_;
66 MockMetrics metrics_;
Paul Stewartca6abd42012-03-01 15:45:29 -080067 MockManager manager_;
Darin Petkov79d74c92012-03-07 17:20:32 +010068 MockDeviceInfo device_info_;
Darin Petkov33af05c2012-02-28 10:10:30 +010069 VPNProvider provider_;
70};
71
Darin Petkov02867712012-03-12 14:25:05 +010072const char VPNProviderTest::kHost[] = "10.8.0.1";
73const char VPNProviderTest::kName[] = "vpn-name";
74
75TEST_F(VPNProviderTest, GetServiceNoType) {
Darin Petkov33af05c2012-02-28 10:10:30 +010076 KeyValueStore args;
77 Error e;
78 args.SetString(flimflam::kTypeProperty, flimflam::kTypeVPN);
Paul Stewart0e51ad92013-07-26 14:42:55 -070079 ServiceRefPtr service = provider_.GetService(args, &e);
Darin Petkov33af05c2012-02-28 10:10:30 +010080 EXPECT_EQ(Error::kNotSupported, e.type());
81 EXPECT_FALSE(service);
82}
83
Darin Petkov02867712012-03-12 14:25:05 +010084TEST_F(VPNProviderTest, GetServiceUnsupportedType) {
Darin Petkov33af05c2012-02-28 10:10:30 +010085 KeyValueStore args;
86 Error e;
87 args.SetString(flimflam::kTypeProperty, flimflam::kTypeVPN);
88 args.SetString(flimflam::kProviderTypeProperty, "unknown-vpn-type");
Darin Petkov02867712012-03-12 14:25:05 +010089 args.SetString(flimflam::kProviderHostProperty, kHost);
Darin Petkov4e02ba22013-04-02 13:44:08 +020090 args.SetString(flimflam::kNameProperty, kName);
Paul Stewart0e51ad92013-07-26 14:42:55 -070091 ServiceRefPtr service = provider_.GetService(args, &e);
Darin Petkov33af05c2012-02-28 10:10:30 +010092 EXPECT_EQ(Error::kNotSupported, e.type());
93 EXPECT_FALSE(service);
94}
95
Darin Petkov02867712012-03-12 14:25:05 +010096TEST_F(VPNProviderTest, GetService) {
Darin Petkov33af05c2012-02-28 10:10:30 +010097 KeyValueStore args;
Darin Petkov33af05c2012-02-28 10:10:30 +010098 args.SetString(flimflam::kTypeProperty, flimflam::kTypeVPN);
99 args.SetString(flimflam::kProviderTypeProperty, flimflam::kProviderOpenVpn);
Darin Petkov02867712012-03-12 14:25:05 +0100100 args.SetString(flimflam::kProviderHostProperty, kHost);
Darin Petkov4e02ba22013-04-02 13:44:08 +0200101 args.SetString(flimflam::kNameProperty, kName);
Paul Stewartbc14fb72013-07-30 08:21:58 -0700102
103 {
104 Error error;
105 ServiceRefPtr service = provider_.FindSimilarService(args, &error);
106 EXPECT_EQ(Error::kNotFound, error.type());
107 EXPECT_EQ(NULL, service.get());
108 }
109
110 EXPECT_EQ(0, GetServiceCount());
111
112 ServiceRefPtr service;
113 {
114 Error error;
115 EXPECT_CALL(manager_, device_info()).WillOnce(Return(&device_info_));
116 EXPECT_CALL(manager_, RegisterService(_));
117 service = provider_.GetService(args, &error);
118 EXPECT_TRUE(error.IsSuccess());
119 ASSERT_TRUE(service);
120 testing::Mock::VerifyAndClearExpectations(&manager_);
121 }
122
123 EXPECT_EQ("vpn_10_8_0_1_vpn_name", service->GetStorageIdentifier());
124 EXPECT_EQ(kName, GetServiceFriendlyName(service));
125
126 EXPECT_EQ(1, GetServiceCount());
Paul Stewart39964fa2012-04-04 09:50:25 -0700127
Darin Petkov9c6e9812013-03-26 13:49:07 +0100128 // Configure the service to set its properties (including Provider.Host).
Paul Stewartbc14fb72013-07-30 08:21:58 -0700129 {
130 Error error;
131 service->Configure(args, &error);
132 EXPECT_TRUE(error.IsSuccess());
133 }
134
135 // None of the calls below should cause a new service to be registered.
136 EXPECT_CALL(manager_, RegisterService(_)).Times(0);
Darin Petkov9c6e9812013-03-26 13:49:07 +0100137
Paul Stewart39964fa2012-04-04 09:50:25 -0700138 // A second call should return the same service.
Paul Stewartbc14fb72013-07-30 08:21:58 -0700139 {
140 Error error;
141 ServiceRefPtr get_service = provider_.GetService(args, &error);
142 EXPECT_TRUE(error.IsSuccess());
143 ASSERT_EQ(service, get_service);
144 }
145
146 EXPECT_EQ(1, GetServiceCount());
147
148 // FindSimilarService should also return this service.
149 {
150 Error error;
151 ServiceRefPtr similar_service = provider_.FindSimilarService(args, &error);
152 EXPECT_TRUE(error.IsSuccess());
153 EXPECT_EQ(service, similar_service);
154 }
155
156 EXPECT_EQ(1, GetServiceCount());
157
158 // However, CreateTemporaryService should create a different service.
159 {
160 Error error;
161 ServiceRefPtr temporary_service =
162 provider_.CreateTemporaryService(args, &error);
163 EXPECT_TRUE(error.IsSuccess());
164 EXPECT_NE(service, temporary_service);
165
166 // However this service will not be part of the provider.
167 EXPECT_EQ(1, GetServiceCount());
168 }
Darin Petkov33af05c2012-02-28 10:10:30 +0100169}
170
Paul Stewartca6abd42012-03-01 15:45:29 -0800171TEST_F(VPNProviderTest, OnDeviceInfoAvailable) {
172 const string kInterfaceName("tun0");
173 const int kInterfaceIndex = 1;
174
175 scoped_ptr<MockVPNDriver> bad_driver(new MockVPNDriver());
176 EXPECT_CALL(*bad_driver.get(), ClaimInterface(_, _))
177 .Times(2)
178 .WillRepeatedly(Return(false));
179 provider_.services_.push_back(
180 new VPNService(&control_, NULL, &metrics_, NULL, bad_driver.release()));
181
182 EXPECT_FALSE(provider_.OnDeviceInfoAvailable(kInterfaceName,
183 kInterfaceIndex));
184
185 scoped_ptr<MockVPNDriver> good_driver(new MockVPNDriver());
186 EXPECT_CALL(*good_driver.get(), ClaimInterface(_, _))
187 .WillOnce(Return(true));
188 provider_.services_.push_back(
189 new VPNService(&control_, NULL, &metrics_, NULL, good_driver.release()));
190
191 scoped_ptr<MockVPNDriver> dup_driver(new MockVPNDriver());
192 EXPECT_CALL(*dup_driver.get(), ClaimInterface(_, _))
193 .Times(0);
194 provider_.services_.push_back(
195 new VPNService(&control_, NULL, &metrics_, NULL, dup_driver.release()));
196
197 EXPECT_TRUE(provider_.OnDeviceInfoAvailable(kInterfaceName, kInterfaceIndex));
198 provider_.services_.clear();
199}
200
Paul Stewart65512e12012-03-26 18:01:08 -0700201TEST_F(VPNProviderTest, RemoveService) {
202 scoped_refptr<MockVPNService> service0(
203 new MockVPNService(&control_, NULL, &metrics_, NULL, NULL));
204 scoped_refptr<MockVPNService> service1(
205 new MockVPNService(&control_, NULL, &metrics_, NULL, NULL));
206 scoped_refptr<MockVPNService> service2(
207 new MockVPNService(&control_, NULL, &metrics_, NULL, NULL));
208
209 provider_.services_.push_back(service0.get());
210 provider_.services_.push_back(service1.get());
211 provider_.services_.push_back(service2.get());
212
213 ASSERT_EQ(3, provider_.services_.size());
214
215 provider_.RemoveService(service1);
216
217 EXPECT_EQ(2, provider_.services_.size());
218 EXPECT_EQ(service0, provider_.services_[0]);
219 EXPECT_EQ(service2, provider_.services_[1]);
220
221 provider_.RemoveService(service2);
222
223 EXPECT_EQ(1, provider_.services_.size());
224 EXPECT_EQ(service0, provider_.services_[0]);
225
226 provider_.RemoveService(service0);
227 EXPECT_EQ(0, provider_.services_.size());
228}
229
Paul Stewart66815332012-04-09 18:09:36 -0700230MATCHER_P(ServiceWithStorageId, storage_id, "") {
231 return arg->GetStorageIdentifier() == storage_id;
232}
233
234TEST_F(VPNProviderTest, CreateServicesFromProfile) {
235 scoped_refptr<MockProfile> profile(
Thieu Le5133b712013-02-19 14:47:21 -0800236 new NiceMock<MockProfile>(&control_, &metrics_, &manager_, ""));
Paul Stewart66815332012-04-09 18:09:36 -0700237 NiceMock<MockStore> storage;
Darin Petkov9c6e9812013-03-26 13:49:07 +0100238 EXPECT_CALL(*profile, GetConstStorage()).WillRepeatedly(Return(&storage));
239 EXPECT_CALL(storage, GetString(_, _, _)).WillRepeatedly(Return(false));
Paul Stewart66815332012-04-09 18:09:36 -0700240
241 std::set<string> groups;
Darin Petkov9c6e9812013-03-26 13:49:07 +0100242
243 const string kNonVPNIdentifier("foo_1");
Paul Stewart66815332012-04-09 18:09:36 -0700244 groups.insert(kNonVPNIdentifier);
Darin Petkov9c6e9812013-03-26 13:49:07 +0100245
246 const string kVPNIdentifierNoProvider("vpn_no_provider");
247 groups.insert(kVPNIdentifierNoProvider);
248
249 const string kVPNIdentifierNoName("vpn_no_name");
250 groups.insert(kVPNIdentifierNoName);
251 const string kOpenVPNProvider(flimflam::kProviderOpenVpn);
252 EXPECT_CALL(storage, GetString(kVPNIdentifierNoName,
253 flimflam::kProviderTypeProperty,
254 _))
255 .WillRepeatedly(DoAll(SetArgumentPointee<2>(kOpenVPNProvider),
256 Return(true)));
257
258 const string kVPNIdentifierNoHost("vpn_no_host");
259 groups.insert(kVPNIdentifierNoHost);
260 EXPECT_CALL(storage, GetString(kVPNIdentifierNoHost,
261 flimflam::kProviderTypeProperty,
262 _))
263 .WillRepeatedly(DoAll(SetArgumentPointee<2>(kOpenVPNProvider),
264 Return(true)));
265 const string kName("name");
266 EXPECT_CALL(storage, GetString(kVPNIdentifierNoHost,
267 flimflam::kNameProperty, _))
268 .WillRepeatedly(DoAll(SetArgumentPointee<2>(kName), Return(true)));
269
270 const string kVPNIdentifierValid("vpn_valid");
271 groups.insert(kVPNIdentifierValid);
272 EXPECT_CALL(storage, GetString(kVPNIdentifierValid,
273 flimflam::kProviderTypeProperty,
274 _))
275 .WillRepeatedly(DoAll(SetArgumentPointee<2>(kOpenVPNProvider),
276 Return(true)));
277 EXPECT_CALL(storage, GetString(kVPNIdentifierValid,
278 flimflam::kNameProperty, _))
279 .WillRepeatedly(DoAll(SetArgumentPointee<2>(kName), Return(true)));
280 const string kHost("1.2.3.4");
281 EXPECT_CALL(storage, GetString(kVPNIdentifierValid,
282 flimflam::kProviderHostProperty, _))
283 .WillRepeatedly(DoAll(SetArgumentPointee<2>(kHost), Return(true)));
284
Paul Stewart66815332012-04-09 18:09:36 -0700285 EXPECT_CALL(storage, GetGroupsWithKey(flimflam::kProviderTypeProperty))
286 .WillRepeatedly(Return(groups));
287
Paul Stewart66815332012-04-09 18:09:36 -0700288 EXPECT_CALL(manager_, device_info())
289 .WillRepeatedly(Return(reinterpret_cast<DeviceInfo *>(NULL)));
Darin Petkov9c6e9812013-03-26 13:49:07 +0100290 EXPECT_CALL(manager_,
291 RegisterService(ServiceWithStorageId(kVPNIdentifierValid)));
292 EXPECT_CALL(*profile,
293 ConfigureService(ServiceWithStorageId(kVPNIdentifierValid)))
294 .WillOnce(Return(true));
Paul Stewart66815332012-04-09 18:09:36 -0700295 provider_.CreateServicesFromProfile(profile);
296
Darin Petkov9c6e9812013-03-26 13:49:07 +0100297 GetServiceAt(0)->driver()->args()->SetString(flimflam::kProviderHostProperty,
298 kHost);
Paul Stewart66815332012-04-09 18:09:36 -0700299 // Calling this again should not create any more services (checked by the
300 // Times(1) above).
301 provider_.CreateServicesFromProfile(profile);
302}
303
Darin Petkov9d1bbe72012-04-25 10:58:59 +0200304TEST_F(VPNProviderTest, CreateService) {
305 static const char kName[] = "test-vpn-service";
306 static const char kStorageID[] = "test_vpn_storage_id";
307 static const char *kTypes[] = {
308 flimflam::kProviderOpenVpn,
309 flimflam::kProviderL2tpIpsec,
310 };
311 const size_t kTypesCount = arraysize(kTypes);
312 EXPECT_CALL(manager_, device_info())
313 .Times(kTypesCount)
314 .WillRepeatedly(Return(&device_info_));
315 EXPECT_CALL(manager_, RegisterService(_)).Times(kTypesCount);
316 for (size_t i = 0; i < kTypesCount; i++) {
317 Error error;
318 VPNServiceRefPtr service =
319 provider_.CreateService(kTypes[i], kName, kStorageID, &error);
320 ASSERT_TRUE(service) << kTypes[i];
321 ASSERT_TRUE(service->driver()) << kTypes[i];
322 EXPECT_EQ(kTypes[i], service->driver()->GetProviderType());
Darin Petkov457728b2013-01-09 09:49:08 +0100323 EXPECT_EQ(kName, GetServiceFriendlyName(service)) << kTypes[i];
Darin Petkov9d1bbe72012-04-25 10:58:59 +0200324 EXPECT_EQ(kStorageID, service->GetStorageIdentifier()) << kTypes[i];
325 EXPECT_TRUE(error.IsSuccess()) << kTypes[i];
326 }
327 Error error;
328 VPNServiceRefPtr unknown_service =
329 provider_.CreateService("unknown-vpn-type", kName, kStorageID, &error);
330 EXPECT_FALSE(unknown_service);
331 EXPECT_EQ(Error::kNotSupported, error.type());
332}
333
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100334TEST_F(VPNProviderTest, HasActiveService) {
335 EXPECT_FALSE(provider_.HasActiveService());
336
337 scoped_refptr<MockVPNService> service0(
338 new MockVPNService(&control_, NULL, &metrics_, NULL, NULL));
339 scoped_refptr<MockVPNService> service1(
340 new MockVPNService(&control_, NULL, &metrics_, NULL, NULL));
341 scoped_refptr<MockVPNService> service2(
342 new MockVPNService(&control_, NULL, &metrics_, NULL, NULL));
343
344 AddService(service0);
345 AddService(service1);
346 AddService(service2);
347 EXPECT_FALSE(provider_.HasActiveService());
348
349 SetConnectState(service1, Service::kStateAssociating);
350 EXPECT_TRUE(provider_.HasActiveService());
351
352 SetConnectState(service1, Service::kStateOnline);
353 EXPECT_TRUE(provider_.HasActiveService());
354}
355
Darin Petkov33af05c2012-02-28 10:10:30 +0100356} // namespace shill