• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
41 using std::string;
42 using std::unique_ptr;
43 using testing::_;
44 using testing::DoAll;
45 using testing::NiceMock;
46 using testing::Return;
47 using testing::SetArgumentPointee;
48 using testing::StartsWith;
49 
50 namespace shill {
51 
52 class VPNProviderTest : public testing::Test {
53  public:
VPNProviderTest()54   VPNProviderTest()
55       : metrics_(nullptr),
56         manager_(&control_, nullptr, &metrics_),
57         device_info_(&control_, nullptr, &metrics_, &manager_),
58         provider_(&control_, nullptr, &metrics_, &manager_) {}
59 
~VPNProviderTest()60   virtual ~VPNProviderTest() {}
61 
62  protected:
63   static const char kHost[];
64   static const char kName[];
65 
GetServiceFriendlyName(const ServiceRefPtr & service)66   string GetServiceFriendlyName(const ServiceRefPtr& service) {
67     return service->friendly_name();
68   }
69 
SetConnectState(const ServiceRefPtr & service,Service::ConnectState state)70   void SetConnectState(const ServiceRefPtr& service,
71                        Service::ConnectState state) {
72     service->state_ = state;
73   }
74 
AddService(const VPNServiceRefPtr & service)75   void AddService(const VPNServiceRefPtr& service) {
76     provider_.services_.push_back(service);
77   }
78 
GetServiceAt(int idx)79   VPNServiceRefPtr GetServiceAt(int idx) {
80     return provider_.services_[idx];
81   }
82 
GetServiceCount() const83   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 
94 const char VPNProviderTest::kHost[] = "10.8.0.1";
95 const char VPNProviderTest::kName[] = "vpn-name";
96 
TEST_F(VPNProviderTest,GetServiceNoType)97 TEST_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 
TEST_F(VPNProviderTest,GetServiceUnsupportedType)106 TEST_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 
TEST_F(VPNProviderTest,GetService)118 TEST_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 
TEST_F(VPNProviderTest,OnDeviceInfoAvailable)193 TEST_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 
TEST_F(VPNProviderTest,RemoveService)223 TEST_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 
252 MATCHER_P(ServiceWithStorageId, storage_id, "") {
253   return arg->GetStorageIdentifier() == storage_id;
254 }
255 
TEST_F(VPNProviderTest,CreateServicesFromProfile)256 TEST_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 
TEST_F(VPNProviderTest,CreateService)290 TEST_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 
TEST_F(VPNProviderTest,CreateTemporaryServiceFromProfile)321 TEST_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 
TEST_F(VPNProviderTest,HasActiveService)385 TEST_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