// 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 #include #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>(const std::vector&, 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(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 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(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