blob: d5e4178a21c3518968aa3f334b4ea694902c4b8d [file] [log] [blame]
// Copyright 2019 The Chromium 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 "platform/impl/tls_data_router_posix.h"
#include <memory>
#include <utility>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "platform/base/ip_address.h"
#include "platform/impl/stream_socket_posix.h"
#include "platform/impl/tls_connection_posix.h"
#include "platform/test/fake_clock.h"
#include "platform/test/fake_task_runner.h"
namespace openscreen {
namespace {
class MockNetworkWaiter final : public SocketHandleWaiter {
public:
using ReadyHandle = SocketHandleWaiter::ReadyHandle;
MockNetworkWaiter() : SocketHandleWaiter(&FakeClock::now) {}
MOCK_METHOD2(
AwaitSocketsReadable,
ErrorOr<std::vector<ReadyHandle>>(const std::vector<SocketHandleRef>&,
const Clock::duration&));
};
class MockSocket : public StreamSocketPosix {
public:
explicit MockSocket(int fd)
: StreamSocketPosix(IPAddress::Version::kV4), handle(fd) {}
const SocketHandle& socket_handle() const override { return handle; }
SocketHandle handle;
};
class MockConnection : public TlsConnectionPosix {
public:
explicit MockConnection(int fd, TaskRunner* task_runner)
: TlsConnectionPosix(std::make_unique<MockSocket>(fd), task_runner) {}
MOCK_METHOD0(SendAvailableBytes, void());
MOCK_METHOD0(TryReceiveMessage, void());
};
} // namespace
class TestingDataRouter : public TlsDataRouterPosix {
public:
explicit TestingDataRouter(SocketHandleWaiter* waiter)
: TlsDataRouterPosix(waiter) {
disable_locking_for_testing_ = true;
}
using TlsDataRouterPosix::IsSocketWatched;
bool AnySocketsWatched() {
std::unique_lock<std::mutex> lock(accept_socket_mutex_);
return !accept_stream_sockets_.empty() && !accept_socket_mappings_.empty();
}
};
class MockObserver : public TestingDataRouter::SocketObserver {
MOCK_METHOD1(OnConnectionPending, void(StreamSocketPosix*));
};
class TlsNetworkingManagerPosixTest : public testing::Test {
public:
TlsNetworkingManagerPosixTest()
: clock_(Clock::now()),
task_runner_(&clock_),
network_manager_(&network_waiter_) {}
FakeTaskRunner* task_runner() { return &task_runner_; }
TestingDataRouter* network_manager() { return &network_manager_; }
private:
FakeClock clock_;
FakeTaskRunner task_runner_;
MockNetworkWaiter network_waiter_;
TestingDataRouter network_manager_;
};
TEST_F(TlsNetworkingManagerPosixTest, SocketsWatchedCorrectly) {
auto socket = std::make_unique<StreamSocketPosix>(IPAddress::Version::kV4);
MockObserver observer;
auto* ptr = socket.get();
ASSERT_FALSE(network_manager()->IsSocketWatched(ptr));
network_manager()->RegisterAcceptObserver(std::move(socket), &observer);
ASSERT_TRUE(network_manager()->IsSocketWatched(ptr));
ASSERT_TRUE(network_manager()->AnySocketsWatched());
network_manager()->DeregisterAcceptObserver(&observer);
ASSERT_FALSE(network_manager()->IsSocketWatched(ptr));
ASSERT_FALSE(network_manager()->AnySocketsWatched());
network_manager()->DeregisterAcceptObserver(&observer);
ASSERT_FALSE(network_manager()->IsSocketWatched(ptr));
ASSERT_FALSE(network_manager()->AnySocketsWatched());
}
TEST_F(TlsNetworkingManagerPosixTest, CallsReadySocket) {
MockConnection connection1(1, task_runner());
MockConnection connection2(2, task_runner());
MockConnection connection3(3, task_runner());
network_manager()->RegisterConnection(&connection1);
network_manager()->RegisterConnection(&connection2);
network_manager()->RegisterConnection(&connection3);
EXPECT_CALL(connection1, SendAvailableBytes()).Times(0);
EXPECT_CALL(connection1, TryReceiveMessage()).Times(1);
EXPECT_CALL(connection2, SendAvailableBytes()).Times(0);
EXPECT_CALL(connection2, TryReceiveMessage()).Times(0);
EXPECT_CALL(connection3, SendAvailableBytes()).Times(0);
EXPECT_CALL(connection3, TryReceiveMessage()).Times(0);
network_manager()->ProcessReadyHandle(connection1.socket_handle(),
SocketHandleWaiter::Flags::kReadable);
EXPECT_CALL(connection1, SendAvailableBytes()).Times(0);
EXPECT_CALL(connection1, TryReceiveMessage()).Times(0);
EXPECT_CALL(connection2, SendAvailableBytes()).Times(1);
EXPECT_CALL(connection2, TryReceiveMessage()).Times(0);
EXPECT_CALL(connection3, SendAvailableBytes()).Times(0);
EXPECT_CALL(connection3, TryReceiveMessage()).Times(0);
network_manager()->ProcessReadyHandle(connection2.socket_handle(),
SocketHandleWaiter::Flags::kWriteable);
}
TEST_F(TlsNetworkingManagerPosixTest, DeregisterTlsConnection) {
MockConnection connection1(1, task_runner());
MockConnection connection2(2, task_runner());
network_manager()->RegisterConnection(&connection1);
network_manager()->RegisterConnection(&connection2);
network_manager()->DeregisterConnection(&connection1);
EXPECT_CALL(connection1, SendAvailableBytes()).Times(0);
EXPECT_CALL(connection1, TryReceiveMessage()).Times(0);
network_manager()->ProcessReadyHandle(connection1.socket_handle(),
SocketHandleWaiter::Flags::kReadable);
EXPECT_CALL(connection2, SendAvailableBytes()).Times(0);
EXPECT_CALL(connection2, TryReceiveMessage()).Times(1);
network_manager()->ProcessReadyHandle(connection2.socket_handle(),
SocketHandleWaiter::Flags::kReadable);
}
} // namespace openscreen