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/socket_handle_waiter_posix.h"
6
7 #include <sys/socket.h>
8
9 #include <chrono>
10 #include <iostream>
11 #include <thread>
12
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
15 #include "platform/impl/socket_handle_posix.h"
16 #include "platform/impl/timeval_posix.h"
17 #include "platform/test/fake_clock.h"
18
19 namespace openscreen {
20 namespace {
21
22 using namespace ::testing;
23 using ::testing::_;
24
25 class MockSubscriber : public SocketHandleWaiter::Subscriber {
26 public:
27 using SocketHandleRef = SocketHandleWaiter::SocketHandleRef;
28 MOCK_METHOD2(ProcessReadyHandle, void(SocketHandleRef, uint32_t));
29 };
30
31 class TestingSocketHandleWaiter : public SocketHandleWaiter {
32 public:
33 using SocketHandleRef = SocketHandleWaiter::SocketHandleRef;
34 using ReadyHandle = SocketHandleWaiter::ReadyHandle;
35
TestingSocketHandleWaiter()36 TestingSocketHandleWaiter() : SocketHandleWaiter(&FakeClock::now) {}
37
38 MOCK_METHOD2(
39 AwaitSocketsReadable,
40 ErrorOr<std::vector<ReadyHandle>>(const std::vector<SocketHandleRef>&,
41 const Clock::duration&));
42
43 FakeClock fake_clock{Clock::time_point{Clock::duration{1234567}}};
44 };
45
46 } // namespace
47
TEST(SocketHandleWaiterTest,BubblesUpAwaitSocketsReadableErrors)48 TEST(SocketHandleWaiterTest, BubblesUpAwaitSocketsReadableErrors) {
49 MockSubscriber subscriber;
50 TestingSocketHandleWaiter waiter;
51 SocketHandle handle0{0};
52 SocketHandle handle1{1};
53 SocketHandle handle2{2};
54 const SocketHandle& handle0_ref = handle0;
55 const SocketHandle& handle1_ref = handle1;
56 const SocketHandle& handle2_ref = handle2;
57
58 waiter.Subscribe(&subscriber, std::cref(handle0_ref));
59 waiter.Subscribe(&subscriber, std::cref(handle1_ref));
60 waiter.Subscribe(&subscriber, std::cref(handle2_ref));
61 Error::Code response = Error::Code::kAgain;
62 EXPECT_CALL(subscriber, ProcessReadyHandle(_, _)).Times(0);
63 EXPECT_CALL(waiter, AwaitSocketsReadable(_, _))
64 .WillOnce(Return(ByMove(response)));
65 waiter.ProcessHandles(Clock::duration{0});
66 }
67
TEST(SocketHandleWaiterTest,WatchedSocketsReturnedToCorrectSubscribers)68 TEST(SocketHandleWaiterTest, WatchedSocketsReturnedToCorrectSubscribers) {
69 MockSubscriber subscriber;
70 MockSubscriber subscriber2;
71 TestingSocketHandleWaiter waiter;
72 SocketHandle handle0{0};
73 SocketHandle handle1{1};
74 SocketHandle handle2{2};
75 SocketHandle handle3{3};
76 const SocketHandle& handle0_ref = handle0;
77 const SocketHandle& handle1_ref = handle1;
78 const SocketHandle& handle2_ref = handle2;
79 const SocketHandle& handle3_ref = handle3;
80
81 waiter.Subscribe(&subscriber, std::cref(handle0_ref));
82 waiter.Subscribe(&subscriber, std::cref(handle2_ref));
83 waiter.Subscribe(&subscriber2, std::cref(handle1_ref));
84 waiter.Subscribe(&subscriber2, std::cref(handle3_ref));
85 constexpr uint32_t r_flags = SocketHandleWaiter::Flags::kReadable;
86 constexpr uint32_t w_flags = SocketHandleWaiter::Flags::kWriteable;
87 constexpr uint32_t rw_flags = SocketHandleWaiter::Flags::kReadable |
88 SocketHandleWaiter::Flags::kWriteable;
89 EXPECT_CALL(subscriber, ProcessReadyHandle(std::cref(handle0_ref), r_flags))
90 .Times(1);
91 EXPECT_CALL(subscriber, ProcessReadyHandle(std::cref(handle2_ref), w_flags))
92 .Times(1);
93 EXPECT_CALL(subscriber2, ProcessReadyHandle(std::cref(handle1_ref), r_flags))
94 .Times(1);
95 EXPECT_CALL(subscriber2, ProcessReadyHandle(std::cref(handle3_ref), rw_flags))
96 .Times(1);
97 EXPECT_CALL(waiter, AwaitSocketsReadable(_, _))
98 .WillOnce(
99 Return(ByMove(std::vector<TestingSocketHandleWaiter::ReadyHandle>{
100 {std::cref(handle0_ref), r_flags},
101 {std::cref(handle1_ref), r_flags},
102 {std::cref(handle2_ref), w_flags},
103 {std::cref(handle3_ref), rw_flags}})));
104 waiter.ProcessHandles(Clock::duration{0});
105 }
106
107 } // namespace openscreen
108