// 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/socket_handle_waiter_posix.h" #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "platform/impl/socket_handle_posix.h" #include "platform/impl/timeval_posix.h" #include "platform/test/fake_clock.h" namespace openscreen { namespace { using namespace ::testing; using ::testing::_; class MockSubscriber : public SocketHandleWaiter::Subscriber { public: using SocketHandleRef = SocketHandleWaiter::SocketHandleRef; MOCK_METHOD2(ProcessReadyHandle, void(SocketHandleRef, uint32_t)); }; class TestingSocketHandleWaiter : public SocketHandleWaiter { public: using SocketHandleRef = SocketHandleWaiter::SocketHandleRef; using ReadyHandle = SocketHandleWaiter::ReadyHandle; TestingSocketHandleWaiter() : SocketHandleWaiter(&FakeClock::now) {} MOCK_METHOD2( AwaitSocketsReadable, ErrorOr>(const std::vector&, const Clock::duration&)); FakeClock fake_clock{Clock::time_point{Clock::duration{1234567}}}; }; } // namespace TEST(SocketHandleWaiterTest, BubblesUpAwaitSocketsReadableErrors) { MockSubscriber subscriber; TestingSocketHandleWaiter waiter; SocketHandle handle0{0}; SocketHandle handle1{1}; SocketHandle handle2{2}; const SocketHandle& handle0_ref = handle0; const SocketHandle& handle1_ref = handle1; const SocketHandle& handle2_ref = handle2; waiter.Subscribe(&subscriber, std::cref(handle0_ref)); waiter.Subscribe(&subscriber, std::cref(handle1_ref)); waiter.Subscribe(&subscriber, std::cref(handle2_ref)); Error::Code response = Error::Code::kAgain; EXPECT_CALL(subscriber, ProcessReadyHandle(_, _)).Times(0); EXPECT_CALL(waiter, AwaitSocketsReadable(_, _)) .WillOnce(Return(ByMove(response))); waiter.ProcessHandles(Clock::duration{0}); } TEST(SocketHandleWaiterTest, WatchedSocketsReturnedToCorrectSubscribers) { MockSubscriber subscriber; MockSubscriber subscriber2; TestingSocketHandleWaiter waiter; SocketHandle handle0{0}; SocketHandle handle1{1}; SocketHandle handle2{2}; SocketHandle handle3{3}; const SocketHandle& handle0_ref = handle0; const SocketHandle& handle1_ref = handle1; const SocketHandle& handle2_ref = handle2; const SocketHandle& handle3_ref = handle3; waiter.Subscribe(&subscriber, std::cref(handle0_ref)); waiter.Subscribe(&subscriber, std::cref(handle2_ref)); waiter.Subscribe(&subscriber2, std::cref(handle1_ref)); waiter.Subscribe(&subscriber2, std::cref(handle3_ref)); constexpr uint32_t r_flags = SocketHandleWaiter::Flags::kReadable; constexpr uint32_t w_flags = SocketHandleWaiter::Flags::kWriteable; constexpr uint32_t rw_flags = SocketHandleWaiter::Flags::kReadable | SocketHandleWaiter::Flags::kWriteable; EXPECT_CALL(subscriber, ProcessReadyHandle(std::cref(handle0_ref), r_flags)) .Times(1); EXPECT_CALL(subscriber, ProcessReadyHandle(std::cref(handle2_ref), w_flags)) .Times(1); EXPECT_CALL(subscriber2, ProcessReadyHandle(std::cref(handle1_ref), r_flags)) .Times(1); EXPECT_CALL(subscriber2, ProcessReadyHandle(std::cref(handle3_ref), rw_flags)) .Times(1); EXPECT_CALL(waiter, AwaitSocketsReadable(_, _)) .WillOnce( Return(ByMove(std::vector{ {std::cref(handle0_ref), r_flags}, {std::cref(handle1_ref), r_flags}, {std::cref(handle2_ref), w_flags}, {std::cref(handle3_ref), rw_flags}}))); waiter.ProcessHandles(Clock::duration{0}); } } // namespace openscreen