blob: 477aafff13a9594ab0b4e3c45b91fcf5dba4d900 [file] [log] [blame]
// Copyright 2014 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shill/vpn/third_party_vpn_driver.h"
#include <gtest/gtest.h>
#include "shill/mock_adaptors.h"
#include "shill/mock_device_info.h"
#include "shill/mock_event_dispatcher.h"
#include "shill/mock_file_io.h"
#include "shill/mock_glib.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_service.h"
#include "shill/mock_store.h"
#include "shill/mock_virtual_device.h"
#include "shill/nice_mock_control.h"
#include "shill/vpn/mock_vpn_service.h"
using testing::_;
using testing::Mock;
using testing::NiceMock;
using testing::Return;
using testing::SetArgumentPointee;
namespace shill {
class ThirdPartyVpnDriverTest : public testing::Test {
public:
ThirdPartyVpnDriverTest()
: device_info_(&control_, &dispatcher_, &metrics_, &manager_),
metrics_(&dispatcher_),
manager_(&control_, &dispatcher_, &metrics_, &glib_),
driver_(new ThirdPartyVpnDriver(&control_, &dispatcher_, &metrics_,
&manager_, &device_info_)),
adaptor_interface_(new ThirdPartyVpnMockAdaptor()),
service_(new MockVPNService(&control_, &dispatcher_, &metrics_,
&manager_, driver_)),
device_(new MockVirtualDevice(&control_, &dispatcher_, &metrics_,
&manager_, kInterfaceName,
kInterfaceIndex, Technology::kVPN)) {}
virtual ~ThirdPartyVpnDriverTest() {}
virtual void SetUp() {
driver_->adaptor_interface_.reset(adaptor_interface_);
driver_->file_io_ = &mock_file_io_;
}
virtual void TearDown() {
driver_->device_ = nullptr;
driver_->service_ = nullptr;
driver_->file_io_ = nullptr;
}
protected:
static const char kConfigName[];
static const char kInterfaceName[];
static const int kInterfaceIndex;
NiceMockControl control_;
NiceMock<MockDeviceInfo> device_info_;
MockEventDispatcher dispatcher_;
MockMetrics metrics_;
MockFileIO mock_file_io_;
MockGLib glib_;
MockManager manager_;
ThirdPartyVpnDriver *driver_; // Owned by |service_|
ThirdPartyVpnMockAdaptor *adaptor_interface_; // Owned by |driver_|
scoped_refptr<MockVPNService> service_;
scoped_refptr<MockVirtualDevice> device_;
};
const char ThirdPartyVpnDriverTest::kConfigName[] = "default-1";
const char ThirdPartyVpnDriverTest::kInterfaceName[] = "tun0";
const int ThirdPartyVpnDriverTest::kInterfaceIndex = 123;
TEST_F(ThirdPartyVpnDriverTest, ConnectAndDisconnect) {
const std::string interface = kInterfaceName;
IOHandler *io_handler = new IOHandler(); // Owned by |driver_|
int fd = 1;
EXPECT_CALL(*service_, SetState(Service::kStateConfiguring)).Times(1);
EXPECT_CALL(device_info_, CreateTunnelInterface(_))
.WillOnce(DoAll(SetArgumentPointee<0>(interface), Return(true)));
Error error;
driver_->Connect(service_, &error);
EXPECT_TRUE(error.IsSuccess());
EXPECT_EQ(kInterfaceName, driver_->tunnel_interface_);
EXPECT_TRUE(driver_->IsConnectTimeoutStarted());
EXPECT_CALL(device_info_, OpenTunnelInterface(interface))
.WillOnce(Return(fd));
EXPECT_CALL(dispatcher_, CreateInputHandler(fd, _, _))
.WillOnce(Return(io_handler));
EXPECT_CALL(*adaptor_interface_, EmitPlatformMessage(static_cast<uint32_t>(
ThirdPartyVpnDriver::kConnected)));
EXPECT_FALSE(driver_->ClaimInterface("eth1", kInterfaceIndex));
EXPECT_TRUE(driver_->ClaimInterface(interface, kInterfaceIndex));
EXPECT_EQ(driver_->active_client_, driver_);
EXPECT_TRUE(driver_->parameters_expected_);
EXPECT_EQ(driver_->io_handler_.get(), io_handler);
ASSERT_TRUE(driver_->device_);
EXPECT_EQ(kInterfaceIndex, driver_->device_->interface_index());
EXPECT_CALL(*service_, SetState(Service::kStateIdle)).Times(1);
EXPECT_CALL(*adaptor_interface_, EmitPlatformMessage(static_cast<uint32_t>(
ThirdPartyVpnDriver::kDisconnected)));
EXPECT_CALL(mock_file_io_, Close(fd));
driver_->Disconnect();
EXPECT_EQ(driver_->io_handler_.get(), nullptr);
}
TEST_F(ThirdPartyVpnDriverTest, SendPacket) {
int fd = 1;
std::string error;
std::vector<uint8_t> ip_packet(5, 0);
driver_->SendPacket(ip_packet, &error);
EXPECT_EQ(error, "Unexpected call");
error.clear();
ThirdPartyVpnDriver::active_client_ = driver_;
driver_->SendPacket(ip_packet, &error);
EXPECT_EQ(error, "Device not open");
driver_->tun_fd_ = fd;
error.clear();
EXPECT_CALL(mock_file_io_, Write(fd, ip_packet.data(), ip_packet.size()))
.WillOnce(Return(ip_packet.size() - 1));
EXPECT_CALL(
*adaptor_interface_,
EmitPlatformMessage(static_cast<uint32_t>(ThirdPartyVpnDriver::kError)));
driver_->SendPacket(ip_packet, &error);
EXPECT_EQ(error, "Partial write");
error.clear();
EXPECT_CALL(mock_file_io_, Write(fd, ip_packet.data(), ip_packet.size()))
.WillOnce(Return(ip_packet.size()));
driver_->SendPacket(ip_packet, &error);
EXPECT_TRUE(error.empty());
driver_->tun_fd_ = -1;
EXPECT_CALL(*adaptor_interface_, EmitPlatformMessage(static_cast<uint32_t>(
ThirdPartyVpnDriver::kDisconnected)));
}
TEST_F(ThirdPartyVpnDriverTest, UpdateConnectionState) {
std::string error;
driver_->UpdateConnectionState(Service::kStateConfiguring, &error);
EXPECT_EQ(error, "Unexpected call");
error.clear();
ThirdPartyVpnDriver::active_client_ = driver_;
driver_->UpdateConnectionState(Service::kStateConfiguring, &error);
EXPECT_EQ(error, "Invalid argument");
error.clear();
driver_->service_ = service_;
EXPECT_CALL(*service_, SetState(Service::kStateConnected)).Times(1);
driver_->UpdateConnectionState(Service::kStateConnected, &error);
EXPECT_TRUE(error.empty());
Mock::VerifyAndClearExpectations(service_.get());
EXPECT_CALL(*service_, SetState(Service::kStateFailure)).Times(1);
EXPECT_CALL(*adaptor_interface_, EmitPlatformMessage(static_cast<uint32_t>(
ThirdPartyVpnDriver::kDisconnected)))
.Times(1);
driver_->UpdateConnectionState(Service::kStateFailure, &error);
EXPECT_TRUE(error.empty());
Mock::VerifyAndClearExpectations(service_.get());
Mock::VerifyAndClearExpectations(adaptor_interface_);
}
TEST_F(ThirdPartyVpnDriverTest, SetParameters) {
std::map<std::string, std::string> parameters;
std::string error;
std::string warning;
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(error, "Unexpected call");
error.clear();
ThirdPartyVpnDriver::active_client_ = driver_;
driver_->parameters_expected_ = true;
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(error,
"address is missing;subnet_prefix is missing;"
"dns_servers is missing;"
"exclusion_list is missing;inclusion_list is missing;");
EXPECT_TRUE(warning.empty());
error.clear();
parameters["address"] = "1234.1.1.1";
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(error,
"address is not a valid IP;subnet_prefix is missing;"
"dns_servers is missing;"
"exclusion_list is missing;inclusion_list is missing;");
EXPECT_TRUE(warning.empty());
error.clear();
parameters["address"] = "123.211.21.18";
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(error,
"subnet_prefix is missing;dns_servers is missing;"
"exclusion_list is missing;inclusion_list is missing;");
EXPECT_TRUE(warning.empty());
error.clear();
parameters["subnet_prefix"] = "123";
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(error,
"subnet_prefix not in expected range;dns_servers is missing;"
"exclusion_list is missing;inclusion_list is missing;");
EXPECT_TRUE(warning.empty());
error.clear();
parameters["subnet_prefix"] = "12";
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(error, "dns_servers is missing;"
"exclusion_list is missing;inclusion_list is missing;");
EXPECT_TRUE(warning.empty());
error.clear();
parameters["dns_servers"] = "12 123123 43902374";
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(error, "dns_servers has no valid values or is empty;"
"exclusion_list is missing;inclusion_list is missing;");
EXPECT_EQ(warning, "12 for dns_servers is invalid;"
"123123 for dns_servers is invalid;"
"43902374 for dns_servers is invalid;");
driver_->device_ =
new MockVirtualDevice(&control_, &dispatcher_, &metrics_, &manager_,
kInterfaceName, kInterfaceIndex, Technology::kVPN);
error.clear();
warning.clear();
parameters["exclusion_list"] =
"400.400.400.400/12 1.1.1.1/44 1.1.1.1/-1 "
"123.211.21.0/23 123.211.21.1/23 123.211.21.0/25 "
"1.1.1.1.1/12 1.1.1/13";
parameters["dns_servers"] = "";
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(error, "dns_servers has no valid values or is empty;"
"inclusion_list is missing;");
EXPECT_EQ(warning,
"400.400.400.400/12 for exclusion_list is invalid;"
"1.1.1.1/44 for exclusion_list is invalid;"
"1.1.1.1/-1 for exclusion_list is invalid;"
"Duplicate entry for 123.211.21.1/23 in exclusion_list found;"
"1.1.1.1.1/12 for exclusion_list is invalid;"
"1.1.1/13 for exclusion_list is invalid;");
error.clear();
warning.clear();
parameters["exclusion_list"] = "0.0.0.0/0 123.211.21.29/31 123.211.21.1/24";
parameters["inclusion_list"] =
"400.400.400.400/12 1.1.1.1/44 1.1.1.1/-1 "
"123.211.22.0/24 123.211.22.1/24 "
"1.1.1.1.1/12 1.1.1/13 123.211.21.0/24";
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(error, "dns_servers has no valid values or is empty;");
EXPECT_EQ(warning,
"400.400.400.400/12 for inclusion_list is invalid;"
"1.1.1.1/44 for inclusion_list is invalid;"
"1.1.1.1/-1 for inclusion_list is invalid;"
"Duplicate entry for 123.211.22.1/24 in inclusion_list found;"
"1.1.1.1.1/12 for inclusion_list is invalid;"
"1.1.1/13 for inclusion_list is invalid;"
"Duplicate entry for 123.211.21.0/24 in inclusion_list found;");
error.clear();
warning.clear();
parameters["dns_servers"] = "123.211.21.18 123.211.21.19";
parameters["inclusion_list"] = "123.211.61.29/7 123.211.42.29/17";
driver_->SetParameters(parameters, &error, &warning);
EXPECT_EQ(driver_->ip_properties_.exclusion_list.size(), 3);
EXPECT_EQ(driver_->ip_properties_.exclusion_list[0], "123.211.21.29/31");
EXPECT_EQ(driver_->ip_properties_.exclusion_list[1], "0.0.0.0/0");
EXPECT_EQ(driver_->ip_properties_.exclusion_list[2], "123.211.21.1/24");
EXPECT_EQ(driver_->ip_properties_.routes.size(), 2);
EXPECT_EQ(driver_->ip_properties_.routes[0].host, "123.211.61.29");
EXPECT_EQ(driver_->ip_properties_.routes[1].host, "123.211.42.29");
EXPECT_EQ(driver_->ip_properties_.routes[0].netmask, "254.0.0.0");
EXPECT_EQ(driver_->ip_properties_.routes[1].netmask, "255.255.128.0");
EXPECT_EQ(driver_->ip_properties_.routes[0].gateway, parameters["address"]);
EXPECT_EQ(driver_->ip_properties_.routes[1].gateway, parameters["address"]);
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
EXPECT_FALSE(driver_->parameters_expected_);
driver_->device_ = nullptr;
}
} // namespace shill