blob: fb23ee0e22bf176309b734a7650ad0c75d322779 [file] [log] [blame]
// 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 <sys/socket.h>
#include <chrono>
#include <iostream>
#include <thread>
#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<std::vector<ReadyHandle>>(const std::vector<SocketHandleRef>&,
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<TestingSocketHandleWaiter::ReadyHandle>{
{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