1//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "shill/vpn/vpn_provider.h"
18
19#include <memory>
20#include <set>
21
22#if defined(__ANDROID__)
23#include <dbus/service_constants.h>
24#else
25#include <chromeos/dbus/service_constants.h>
26#endif  // __ANDROID__
27#include <gtest/gtest.h>
28
29#include "shill/error.h"
30#include "shill/fake_store.h"
31#include "shill/mock_adaptors.h"
32#include "shill/mock_device_info.h"
33#include "shill/mock_manager.h"
34#include "shill/mock_metrics.h"
35#include "shill/mock_profile.h"
36#include "shill/mock_store.h"
37#include "shill/nice_mock_control.h"
38#include "shill/vpn/mock_vpn_driver.h"
39#include "shill/vpn/mock_vpn_service.h"
40
41using std::string;
42using std::unique_ptr;
43using testing::_;
44using testing::DoAll;
45using testing::NiceMock;
46using testing::Return;
47using testing::SetArgumentPointee;
48using testing::StartsWith;
49
50namespace shill {
51
52class VPNProviderTest : public testing::Test {
53 public:
54  VPNProviderTest()
55      : metrics_(nullptr),
56        manager_(&control_, nullptr, &metrics_),
57        device_info_(&control_, nullptr, &metrics_, &manager_),
58        provider_(&control_, nullptr, &metrics_, &manager_) {}
59
60  virtual ~VPNProviderTest() {}
61
62 protected:
63  static const char kHost[];
64  static const char kName[];
65
66  string GetServiceFriendlyName(const ServiceRefPtr& service) {
67    return service->friendly_name();
68  }
69
70  void SetConnectState(const ServiceRefPtr& service,
71                       Service::ConnectState state) {
72    service->state_ = state;
73  }
74
75  void AddService(const VPNServiceRefPtr& service) {
76    provider_.services_.push_back(service);
77  }
78
79  VPNServiceRefPtr GetServiceAt(int idx) {
80    return provider_.services_[idx];
81  }
82
83  size_t GetServiceCount() const {
84    return provider_.services_.size();
85  }
86
87  NiceMockControl control_;
88  MockMetrics metrics_;
89  MockManager manager_;
90  MockDeviceInfo device_info_;
91  VPNProvider provider_;
92};
93
94const char VPNProviderTest::kHost[] = "10.8.0.1";
95const char VPNProviderTest::kName[] = "vpn-name";
96
97TEST_F(VPNProviderTest, GetServiceNoType) {
98  KeyValueStore args;
99  Error e;
100  args.SetString(kTypeProperty, kTypeVPN);
101  ServiceRefPtr service = provider_.GetService(args, &e);
102  EXPECT_EQ(Error::kNotSupported, e.type());
103  EXPECT_FALSE(service);
104}
105
106TEST_F(VPNProviderTest, GetServiceUnsupportedType) {
107  KeyValueStore args;
108  Error e;
109  args.SetString(kTypeProperty, kTypeVPN);
110  args.SetString(kProviderTypeProperty, "unknown-vpn-type");
111  args.SetString(kProviderHostProperty, kHost);
112  args.SetString(kNameProperty, kName);
113  ServiceRefPtr service = provider_.GetService(args, &e);
114  EXPECT_EQ(Error::kNotSupported, e.type());
115  EXPECT_FALSE(service);
116}
117
118TEST_F(VPNProviderTest, GetService) {
119  KeyValueStore args;
120  args.SetString(kTypeProperty, kTypeVPN);
121  args.SetString(kProviderTypeProperty, kProviderOpenVpn);
122  args.SetString(kProviderHostProperty, kHost);
123  args.SetString(kNameProperty, kName);
124
125  {
126    Error error;
127    ServiceRefPtr service = provider_.FindSimilarService(args, &error);
128    EXPECT_EQ(Error::kNotFound, error.type());
129    EXPECT_EQ(nullptr, service.get());
130  }
131
132  EXPECT_EQ(0, GetServiceCount());
133
134  ServiceRefPtr service;
135  {
136    Error error;
137    EXPECT_CALL(manager_, device_info()).WillOnce(Return(&device_info_));
138    EXPECT_CALL(manager_, RegisterService(_));
139    service = provider_.GetService(args, &error);
140    EXPECT_TRUE(error.IsSuccess());
141    ASSERT_TRUE(service);
142    testing::Mock::VerifyAndClearExpectations(&manager_);
143  }
144
145  EXPECT_EQ("vpn_10_8_0_1_vpn_name", service->GetStorageIdentifier());
146  EXPECT_EQ(kName, GetServiceFriendlyName(service));
147
148  EXPECT_EQ(1, GetServiceCount());
149
150  // Configure the service to set its properties (including Provider.Host).
151  {
152    Error error;
153    service->Configure(args, &error);
154    EXPECT_TRUE(error.IsSuccess());
155  }
156
157  // None of the calls below should cause a new service to be registered.
158  EXPECT_CALL(manager_, RegisterService(_)).Times(0);
159
160  // A second call should return the same service.
161  {
162    Error error;
163    ServiceRefPtr get_service = provider_.GetService(args, &error);
164    EXPECT_TRUE(error.IsSuccess());
165    ASSERT_EQ(service, get_service);
166  }
167
168  EXPECT_EQ(1, GetServiceCount());
169
170  // FindSimilarService should also return this service.
171  {
172    Error error;
173    ServiceRefPtr similar_service = provider_.FindSimilarService(args, &error);
174    EXPECT_TRUE(error.IsSuccess());
175    EXPECT_EQ(service, similar_service);
176  }
177
178  EXPECT_EQ(1, GetServiceCount());
179
180  // However, CreateTemporaryService should create a different service.
181  {
182    Error error;
183    ServiceRefPtr temporary_service =
184        provider_.CreateTemporaryService(args, &error);
185    EXPECT_TRUE(error.IsSuccess());
186    EXPECT_NE(service, temporary_service);
187
188    // However this service will not be part of the provider.
189    EXPECT_EQ(1, GetServiceCount());
190  }
191}
192
193TEST_F(VPNProviderTest, OnDeviceInfoAvailable) {
194  const string kInterfaceName("tun0");
195  const int kInterfaceIndex = 1;
196
197  unique_ptr<MockVPNDriver> bad_driver(new MockVPNDriver());
198  EXPECT_CALL(*bad_driver.get(), ClaimInterface(_, _))
199      .Times(2)
200      .WillRepeatedly(Return(false));
201  provider_.services_.push_back(new VPNService(&control_, nullptr, &metrics_,
202                                               nullptr, bad_driver.release()));
203
204  EXPECT_FALSE(provider_.OnDeviceInfoAvailable(kInterfaceName,
205                                               kInterfaceIndex));
206
207  unique_ptr<MockVPNDriver> good_driver(new MockVPNDriver());
208  EXPECT_CALL(*good_driver.get(), ClaimInterface(_, _))
209      .WillOnce(Return(true));
210  provider_.services_.push_back(new VPNService(&control_, nullptr, &metrics_,
211                                               nullptr, good_driver.release()));
212
213  unique_ptr<MockVPNDriver> dup_driver(new MockVPNDriver());
214  EXPECT_CALL(*dup_driver.get(), ClaimInterface(_, _))
215      .Times(0);
216  provider_.services_.push_back(new VPNService(&control_, nullptr, &metrics_,
217                                               nullptr, dup_driver.release()));
218
219  EXPECT_TRUE(provider_.OnDeviceInfoAvailable(kInterfaceName, kInterfaceIndex));
220  provider_.services_.clear();
221}
222
223TEST_F(VPNProviderTest, RemoveService) {
224  scoped_refptr<MockVPNService> service0(
225      new MockVPNService(&control_, nullptr, &metrics_, nullptr, nullptr));
226  scoped_refptr<MockVPNService> service1(
227      new MockVPNService(&control_, nullptr, &metrics_, nullptr, nullptr));
228  scoped_refptr<MockVPNService> service2(
229      new MockVPNService(&control_, nullptr, &metrics_, nullptr, nullptr));
230
231  provider_.services_.push_back(service0.get());
232  provider_.services_.push_back(service1.get());
233  provider_.services_.push_back(service2.get());
234
235  ASSERT_EQ(3, provider_.services_.size());
236
237  provider_.RemoveService(service1);
238
239  EXPECT_EQ(2, provider_.services_.size());
240  EXPECT_EQ(service0, provider_.services_[0]);
241  EXPECT_EQ(service2, provider_.services_[1]);
242
243  provider_.RemoveService(service2);
244
245  EXPECT_EQ(1, provider_.services_.size());
246  EXPECT_EQ(service0, provider_.services_[0]);
247
248  provider_.RemoveService(service0);
249  EXPECT_EQ(0, provider_.services_.size());
250}
251
252MATCHER_P(ServiceWithStorageId, storage_id, "") {
253  return arg->GetStorageIdentifier() == storage_id;
254}
255
256TEST_F(VPNProviderTest, CreateServicesFromProfile) {
257  FakeStore storage;
258  storage.SetString("no_type", "Name", "No Type Entry");
259  storage.SetString("no_vpn", "Type", "wimax");
260  storage.SetString("vpn_no_provider_type", "Type", "vpn");
261  storage.SetString("vpn_no_name", "Type", "vpn");
262  storage.SetString("vpn_no_name", "Provider.Type", "openvpn");
263  storage.SetString("vpn_no_host", "Type", "vpn");
264  storage.SetString("vpn_no_host", "Provider.Type", "openvpn");
265  storage.SetString("vpn_ho_host", "Name", "name");
266  storage.SetString("vpn_complete", "Type", "vpn");
267  storage.SetString("vpn_complete", "Provider.Type", "openvpn");
268  storage.SetString("vpn_complete", "Name", "name");
269  storage.SetString("vpn_complete", "Provider.Host", "1.2.3.4");
270
271  scoped_refptr<MockProfile> profile(
272      new NiceMock<MockProfile>(&control_, &metrics_, &manager_, ""));
273  EXPECT_CALL(*profile, GetConstStorage()).WillRepeatedly(Return(&storage));
274
275  EXPECT_CALL(manager_, device_info()).WillRepeatedly(Return(nullptr));
276  EXPECT_CALL(manager_,
277              RegisterService(ServiceWithStorageId("vpn_complete")));
278  EXPECT_CALL(*profile,
279              ConfigureService(ServiceWithStorageId("vpn_complete")))
280      .WillOnce(Return(true));
281  provider_.CreateServicesFromProfile(profile);
282
283  GetServiceAt(0)->driver()->args()->SetString(kProviderHostProperty,
284                                               "1.2.3.4");
285  // Calling this again should not create any more services (checked by the
286  // Times(1) above).
287  provider_.CreateServicesFromProfile(profile);
288}
289
290TEST_F(VPNProviderTest, CreateService) {
291  static const char kName[] = "test-vpn-service";
292  static const char kStorageID[] = "test_vpn_storage_id";
293  static const char* kTypes[] = {
294    kProviderOpenVpn,
295    kProviderL2tpIpsec,
296    kProviderThirdPartyVpn
297  };
298  const size_t kTypesCount = arraysize(kTypes);
299  EXPECT_CALL(manager_, device_info())
300      .Times(kTypesCount)
301      .WillRepeatedly(Return(&device_info_));
302  EXPECT_CALL(manager_, RegisterService(_)).Times(kTypesCount);
303  for (size_t i = 0; i < kTypesCount; i++) {
304    Error error;
305    VPNServiceRefPtr service =
306        provider_.CreateService(kTypes[i], kName, kStorageID, &error);
307    ASSERT_TRUE(service) << kTypes[i];
308    ASSERT_TRUE(service->driver()) << kTypes[i];
309    EXPECT_EQ(kTypes[i], service->driver()->GetProviderType());
310    EXPECT_EQ(kName, GetServiceFriendlyName(service)) << kTypes[i];
311    EXPECT_EQ(kStorageID, service->GetStorageIdentifier()) << kTypes[i];
312    EXPECT_TRUE(error.IsSuccess()) << kTypes[i];
313  }
314  Error error;
315  VPNServiceRefPtr unknown_service =
316      provider_.CreateService("unknown-vpn-type", kName, kStorageID, &error);
317  EXPECT_FALSE(unknown_service);
318  EXPECT_EQ(Error::kNotSupported, error.type());
319}
320
321TEST_F(VPNProviderTest, CreateTemporaryServiceFromProfile) {
322  FakeStore storage;
323  storage.SetString("no_vpn", "Type", "wimax");
324  storage.SetString("vpn_no_provider_type", "Type", "vpn");
325  storage.SetString("vpn_no_name", "Type", "vpn");
326  storage.SetString("vpn_no_name", "Provider.Type", "openvpn");
327  storage.SetString("vpn_no_host", "Type", "vpn");
328  storage.SetString("vpn_no_host", "Provider.Type", "openvpn");
329  storage.SetString("vpn_no_host", "Name", "name");
330  storage.SetString("vpn_complete", "Type", "vpn");
331  storage.SetString("vpn_complete", "Provider.Type", "openvpn");
332  storage.SetString("vpn_complete", "Name", "name");
333  storage.SetString("vpn_complete", "Provider.Host", "1.2.3.4");
334
335  scoped_refptr<MockProfile> profile(
336      new NiceMock<MockProfile>(&control_, &metrics_, &manager_, ""));
337  EXPECT_CALL(*profile, GetConstStorage()).WillRepeatedly(Return(&storage));
338  Error error;
339
340  // Non VPN entry.
341  EXPECT_EQ(nullptr,
342            provider_.CreateTemporaryServiceFromProfile(profile,
343                                                        "no_vpn",
344                                                        &error));
345  EXPECT_FALSE(error.IsSuccess());
346  EXPECT_THAT(error.message(),
347              StartsWith("Unspecified or invalid network type"));
348
349  // VPN type not specified.
350  error.Reset();
351  EXPECT_EQ(nullptr,
352            provider_.CreateTemporaryServiceFromProfile(profile,
353                                                        "vpn_no_provider_type",
354                                                        &error));
355  EXPECT_FALSE(error.IsSuccess());
356  EXPECT_THAT(error.message(), StartsWith("VPN type not specified"));
357
358  // Name not specified.
359  error.Reset();
360  EXPECT_EQ(nullptr,
361            provider_.CreateTemporaryServiceFromProfile(profile,
362                                                        "vpn_no_name",
363                                                        &error));
364  EXPECT_FALSE(error.IsSuccess());
365  EXPECT_THAT(error.message(), StartsWith("Network name not specified"));
366
367  // Host not specified.
368  error.Reset();
369  EXPECT_EQ(nullptr,
370            provider_.CreateTemporaryServiceFromProfile(profile,
371                                                        "vpn_no_host",
372                                                        &error));
373  EXPECT_FALSE(error.IsSuccess());
374  EXPECT_THAT(error.message(), StartsWith("Host not specified"));
375
376  // Valid VPN service entry.
377  error.Reset();
378  EXPECT_NE(nullptr,
379            provider_.CreateTemporaryServiceFromProfile(profile,
380                                                        "vpn_complete",
381                                                        &error));
382  EXPECT_TRUE(error.IsSuccess());
383}
384
385TEST_F(VPNProviderTest, HasActiveService) {
386  EXPECT_FALSE(provider_.HasActiveService());
387
388  scoped_refptr<MockVPNService> service0(
389      new MockVPNService(&control_, nullptr, &metrics_, nullptr, nullptr));
390  scoped_refptr<MockVPNService> service1(
391      new MockVPNService(&control_, nullptr, &metrics_, nullptr, nullptr));
392  scoped_refptr<MockVPNService> service2(
393      new MockVPNService(&control_, nullptr, &metrics_, nullptr, nullptr));
394
395  AddService(service0);
396  AddService(service1);
397  AddService(service2);
398  EXPECT_FALSE(provider_.HasActiveService());
399
400  SetConnectState(service1, Service::kStateAssociating);
401  EXPECT_TRUE(provider_.HasActiveService());
402
403  SetConnectState(service1, Service::kStateOnline);
404  EXPECT_TRUE(provider_.HasActiveService());
405}
406
407}  // namespace shill
408