blob: cebd7481e05b0245495283ca14f61da2954e7c45 [file] [log] [blame]
// Copyright 2021 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/vpn_connection.h"
#include <memory>
#include <string>
#include <utility>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "shill/ipconfig.h"
#include "shill/service.h"
#include "shill/test_event_dispatcher.h"
#include "shill/vpn/vpn_connection_under_test.h"
namespace shill {
namespace {
constexpr char kTestIfName[] = "vpn0";
constexpr int kTestIfIndex = 123;
constexpr char kTestIPAddress[] = "192.168.1.2";
// We only compare |address| in this test for simplicity.
MATCHER_P(IPPropertiesEq, rhs, "") {
return arg.address == rhs.address;
}
class MockCallbacks {
public:
MOCK_METHOD(void,
OnConnected,
(const std::string& link_name,
int interface_index,
const IPConfig::Properties& ip_properties));
MOCK_METHOD(void, OnFailure, (Service::ConnectFailure));
MOCK_METHOD(void, OnStopped, ());
};
class VPNConnectionTest : public testing::Test {
public:
VPNConnectionTest() {
auto callbacks = std::make_unique<VPNConnection::Callbacks>(
base::BindRepeating(&MockCallbacks::OnConnected,
base::Unretained(&callbacks_)),
base::BindOnce(&MockCallbacks::OnFailure,
base::Unretained(&callbacks_)),
base::BindOnce(&MockCallbacks::OnStopped,
base::Unretained(&callbacks_)));
vpn_connection_ = std::make_unique<VPNConnectionUnderTest>(
std::move(callbacks), &dispatcher_);
test_ip_properties_.address = kTestIPAddress;
}
protected:
IPConfig::Properties test_ip_properties_;
EventDispatcherForTest dispatcher_;
MockCallbacks callbacks_;
std::unique_ptr<VPNConnectionUnderTest> vpn_connection_;
};
TEST_F(VPNConnectionTest, ConnectDisconnect) {
vpn_connection_->Connect();
EXPECT_CALL(*vpn_connection_, OnConnect());
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kConnecting);
dispatcher_.task_environment().RunUntilIdle();
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kConnecting);
vpn_connection_->TriggerConnected(kTestIfName, kTestIfIndex,
test_ip_properties_);
EXPECT_CALL(callbacks_, OnConnected(kTestIfName, kTestIfIndex,
IPPropertiesEq(test_ip_properties_)));
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kConnected);
dispatcher_.task_environment().RunUntilIdle();
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kConnected);
vpn_connection_->Disconnect();
EXPECT_CALL(*vpn_connection_, OnDisconnect());
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kDisconnecting);
dispatcher_.task_environment().RunUntilIdle();
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kDisconnecting);
vpn_connection_->TriggerStopped();
EXPECT_CALL(callbacks_, OnStopped());
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kStopped);
dispatcher_.task_environment().RunUntilIdle();
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kStopped);
}
TEST_F(VPNConnectionTest, ConnectingFailure) {
vpn_connection_->Connect();
dispatcher_.task_environment().RunUntilIdle();
vpn_connection_->TriggerFailure(Service::kFailureInternal, "");
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kDisconnecting);
EXPECT_CALL(*vpn_connection_, OnDisconnect());
EXPECT_CALL(callbacks_, OnFailure(Service::kFailureInternal));
dispatcher_.task_environment().RunUntilIdle();
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kDisconnecting);
}
TEST_F(VPNConnectionTest, ConnectedFailure) {
vpn_connection_->Connect();
dispatcher_.task_environment().RunUntilIdle();
vpn_connection_->TriggerConnected(kTestIfName, kTestIfIndex,
test_ip_properties_);
dispatcher_.task_environment().RunUntilIdle();
vpn_connection_->TriggerFailure(Service::kFailureInternal, "");
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kDisconnecting);
EXPECT_CALL(*vpn_connection_, OnDisconnect());
EXPECT_CALL(callbacks_, OnFailure(Service::kFailureInternal));
dispatcher_.task_environment().RunUntilIdle();
EXPECT_EQ(vpn_connection_->state(), VPNConnection::State::kDisconnecting);
}
} // namespace
} // namespace shill