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