1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "platform/impl/tls_data_router_posix.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
12 #include "platform/base/ip_address.h"
13 #include "platform/impl/stream_socket_posix.h"
14 #include "platform/impl/tls_connection_posix.h"
15 #include "platform/test/fake_clock.h"
16 #include "platform/test/fake_task_runner.h"
17
18 namespace openscreen {
19 namespace {
20
21 class MockNetworkWaiter final : public SocketHandleWaiter {
22 public:
23 using ReadyHandle = SocketHandleWaiter::ReadyHandle;
24
MockNetworkWaiter()25 MockNetworkWaiter() : SocketHandleWaiter(&FakeClock::now) {}
26
27 MOCK_METHOD2(
28 AwaitSocketsReadable,
29 ErrorOr<std::vector<ReadyHandle>>(const std::vector<SocketHandleRef>&,
30 const Clock::duration&));
31 };
32
33 class MockSocket : public StreamSocketPosix {
34 public:
MockSocket(int fd)35 explicit MockSocket(int fd)
36 : StreamSocketPosix(IPAddress::Version::kV4), handle(fd) {}
37
socket_handle() const38 const SocketHandle& socket_handle() const override { return handle; }
39
40 SocketHandle handle;
41 };
42
43 class MockConnection : public TlsConnectionPosix {
44 public:
MockConnection(int fd,TaskRunner * task_runner)45 explicit MockConnection(int fd, TaskRunner* task_runner)
46 : TlsConnectionPosix(std::make_unique<MockSocket>(fd), task_runner) {}
47 MOCK_METHOD0(SendAvailableBytes, void());
48 MOCK_METHOD0(TryReceiveMessage, void());
49 };
50
51 } // namespace
52
53 class TestingDataRouter : public TlsDataRouterPosix {
54 public:
TestingDataRouter(SocketHandleWaiter * waiter)55 explicit TestingDataRouter(SocketHandleWaiter* waiter)
56 : TlsDataRouterPosix(waiter) {
57 disable_locking_for_testing_ = true;
58 }
59
60 using TlsDataRouterPosix::IsSocketWatched;
61
AnySocketsWatched()62 bool AnySocketsWatched() {
63 std::unique_lock<std::mutex> lock(accept_socket_mutex_);
64 return !accept_stream_sockets_.empty() && !accept_socket_mappings_.empty();
65 }
66 };
67
68 class MockObserver : public TestingDataRouter::SocketObserver {
69 MOCK_METHOD1(OnConnectionPending, void(StreamSocketPosix*));
70 };
71
72 class TlsNetworkingManagerPosixTest : public testing::Test {
73 public:
TlsNetworkingManagerPosixTest()74 TlsNetworkingManagerPosixTest()
75 : clock_(Clock::now()),
76 task_runner_(&clock_),
77 network_manager_(&network_waiter_) {}
78
task_runner()79 FakeTaskRunner* task_runner() { return &task_runner_; }
network_manager()80 TestingDataRouter* network_manager() { return &network_manager_; }
81
82 private:
83 FakeClock clock_;
84 FakeTaskRunner task_runner_;
85 MockNetworkWaiter network_waiter_;
86 TestingDataRouter network_manager_;
87 };
88
TEST_F(TlsNetworkingManagerPosixTest,SocketsWatchedCorrectly)89 TEST_F(TlsNetworkingManagerPosixTest, SocketsWatchedCorrectly) {
90 auto socket = std::make_unique<StreamSocketPosix>(IPAddress::Version::kV4);
91 MockObserver observer;
92
93 auto* ptr = socket.get();
94 ASSERT_FALSE(network_manager()->IsSocketWatched(ptr));
95
96 network_manager()->RegisterAcceptObserver(std::move(socket), &observer);
97 ASSERT_TRUE(network_manager()->IsSocketWatched(ptr));
98 ASSERT_TRUE(network_manager()->AnySocketsWatched());
99
100 network_manager()->DeregisterAcceptObserver(&observer);
101 ASSERT_FALSE(network_manager()->IsSocketWatched(ptr));
102 ASSERT_FALSE(network_manager()->AnySocketsWatched());
103
104 network_manager()->DeregisterAcceptObserver(&observer);
105 ASSERT_FALSE(network_manager()->IsSocketWatched(ptr));
106 ASSERT_FALSE(network_manager()->AnySocketsWatched());
107 }
108
TEST_F(TlsNetworkingManagerPosixTest,CallsReadySocket)109 TEST_F(TlsNetworkingManagerPosixTest, CallsReadySocket) {
110 MockConnection connection1(1, task_runner());
111 MockConnection connection2(2, task_runner());
112 MockConnection connection3(3, task_runner());
113 network_manager()->RegisterConnection(&connection1);
114 network_manager()->RegisterConnection(&connection2);
115 network_manager()->RegisterConnection(&connection3);
116
117 EXPECT_CALL(connection1, SendAvailableBytes()).Times(0);
118 EXPECT_CALL(connection1, TryReceiveMessage()).Times(1);
119 EXPECT_CALL(connection2, SendAvailableBytes()).Times(0);
120 EXPECT_CALL(connection2, TryReceiveMessage()).Times(0);
121 EXPECT_CALL(connection3, SendAvailableBytes()).Times(0);
122 EXPECT_CALL(connection3, TryReceiveMessage()).Times(0);
123 network_manager()->ProcessReadyHandle(connection1.socket_handle(),
124 SocketHandleWaiter::Flags::kReadable);
125
126 EXPECT_CALL(connection1, SendAvailableBytes()).Times(0);
127 EXPECT_CALL(connection1, TryReceiveMessage()).Times(0);
128 EXPECT_CALL(connection2, SendAvailableBytes()).Times(1);
129 EXPECT_CALL(connection2, TryReceiveMessage()).Times(0);
130 EXPECT_CALL(connection3, SendAvailableBytes()).Times(0);
131 EXPECT_CALL(connection3, TryReceiveMessage()).Times(0);
132 network_manager()->ProcessReadyHandle(connection2.socket_handle(),
133 SocketHandleWaiter::Flags::kWriteable);
134 }
135
TEST_F(TlsNetworkingManagerPosixTest,DeregisterTlsConnection)136 TEST_F(TlsNetworkingManagerPosixTest, DeregisterTlsConnection) {
137 MockConnection connection1(1, task_runner());
138 MockConnection connection2(2, task_runner());
139 network_manager()->RegisterConnection(&connection1);
140 network_manager()->RegisterConnection(&connection2);
141
142 network_manager()->DeregisterConnection(&connection1);
143 EXPECT_CALL(connection1, SendAvailableBytes()).Times(0);
144 EXPECT_CALL(connection1, TryReceiveMessage()).Times(0);
145 network_manager()->ProcessReadyHandle(connection1.socket_handle(),
146 SocketHandleWaiter::Flags::kReadable);
147 EXPECT_CALL(connection2, SendAvailableBytes()).Times(0);
148 EXPECT_CALL(connection2, TryReceiveMessage()).Times(1);
149 network_manager()->ProcessReadyHandle(connection2.socket_handle(),
150 SocketHandleWaiter::Flags::kReadable);
151 }
152
153 } // namespace openscreen
154