Home | History | Annotate | Download | only in vpn
      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:
     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 
     94 const char VPNProviderTest::kHost[] = "10.8.0.1";
     95 const char VPNProviderTest::kName[] = "vpn-name";
     96 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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