• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/udp_socket_reader_posix.h"
6 
7 #include "gmock/gmock.h"
8 #include "gtest/gtest.h"
9 #include "platform/api/time.h"
10 #include "platform/impl/socket_handle_posix.h"
11 #include "platform/impl/udp_socket_posix.h"
12 #include "platform/test/fake_clock.h"
13 #include "platform/test/fake_task_runner.h"
14 #include "platform/test/fake_udp_socket.h"
15 
16 namespace openscreen {
17 namespace {
18 
19 using namespace ::testing;
20 using ::testing::_;
21 using ::testing::Invoke;
22 
23 class MockUdpSocketPosix : public UdpSocketPosix {
24  public:
MockUdpSocketPosix(TaskRunner * task_runner,Client * client,int fd,Version version=Version::kV4)25   explicit MockUdpSocketPosix(TaskRunner* task_runner,
26                               Client* client,
27                               int fd,
28                               Version version = Version::kV4)
29       : UdpSocketPosix(task_runner, client, SocketHandle(fd), IPEndpoint()),
30         version_(version) {}
31   ~MockUdpSocketPosix() override = default;
32 
IsIPv4() const33   bool IsIPv4() const override { return version_ == UdpSocket::Version::kV4; }
34 
IsIPv6() const35   bool IsIPv6() const override { return version_ == UdpSocket::Version::kV6; }
36 
37   MOCK_METHOD0(Bind, void());
38   MOCK_METHOD1(SetMulticastOutboundInterface, void(NetworkInterfaceIndex));
39   MOCK_METHOD2(JoinMulticastGroup,
40                void(const IPAddress&, NetworkInterfaceIndex));
41   MOCK_METHOD3(SendMessage, void(const void*, size_t, const IPEndpoint&));
42   MOCK_METHOD1(SetDscp, void(DscpMode));
43 
44  private:
45   Version version_;
46 };
47 
48 // Mock event waiter
49 class MockNetworkWaiter final : public SocketHandleWaiter {
50  public:
51   using ReadyHandle = SocketHandleWaiter::ReadyHandle;
52 
MockNetworkWaiter()53   MockNetworkWaiter() : SocketHandleWaiter(&FakeClock::now) {}
54   ~MockNetworkWaiter() override = default;
55 
56   MOCK_METHOD2(
57       AwaitSocketsReadable,
58       ErrorOr<std::vector<ReadyHandle>>(const std::vector<SocketHandleRef>&,
59                                         const Clock::duration&));
60 
61   FakeClock fake_clock{Clock::time_point{Clock::duration{1234567}}};
62 };
63 
64 // Mock Task Runner
65 class MockTaskRunner final : public TaskRunner {
66  public:
MockTaskRunner()67   MockTaskRunner() {
68     tasks_posted = 0;
69     delayed_tasks_posted = 0;
70   }
71 
PostPackagedTask(Task t)72   void PostPackagedTask(Task t) override {
73     tasks_posted++;
74     t();
75   }
76 
PostPackagedTaskWithDelay(Task t,Clock::duration duration)77   void PostPackagedTaskWithDelay(Task t, Clock::duration duration) override {
78     delayed_tasks_posted++;
79     t();
80   }
81 
IsRunningOnTaskRunner()82   bool IsRunningOnTaskRunner() override { return true; }
83 
84   uint32_t tasks_posted;
85   uint32_t delayed_tasks_posted;
86 };
87 
88 }  // namespace
89 
90 // Class extending NetworkWaiter to allow for looking at protected data.
91 class TestingUdpSocketReader final : public UdpSocketReaderPosix {
92  public:
TestingUdpSocketReader(SocketHandleWaiter * waiter)93   explicit TestingUdpSocketReader(SocketHandleWaiter* waiter)
94       : UdpSocketReaderPosix(waiter) {}
95 
OnDestroy(UdpSocket * socket)96   void OnDestroy(UdpSocket* socket) override {
97     OnDelete(static_cast<UdpSocketPosix*>(socket), true);
98   }
99 
IsMappedRead(UdpSocketPosix * socket) const100   bool IsMappedRead(UdpSocketPosix* socket) const {
101     return IsMappedReadForTesting(socket);
102   }
103 };
104 
TEST(UdpSocketReaderTest,WatchReadableSucceeds)105 TEST(UdpSocketReaderTest, WatchReadableSucceeds) {
106   std::unique_ptr<SocketHandleWaiter> mock_waiter =
107       std::unique_ptr<SocketHandleWaiter>(new MockNetworkWaiter());
108   std::unique_ptr<TaskRunner> task_runner =
109       std::unique_ptr<TaskRunner>(new MockTaskRunner());
110   FakeUdpSocket::MockClient client;
111   std::unique_ptr<MockUdpSocketPosix> socket =
112       std::make_unique<MockUdpSocketPosix>(task_runner.get(), &client, 42,
113                                            UdpSocket::Version::kV4);
114 }
115 
TEST(UdpSocketReaderTest,UnwatchReadableSucceeds)116 TEST(UdpSocketReaderTest, UnwatchReadableSucceeds) {
117   std::unique_ptr<SocketHandleWaiter> mock_waiter =
118       std::unique_ptr<SocketHandleWaiter>(new MockNetworkWaiter());
119   std::unique_ptr<TaskRunner> task_runner =
120       std::unique_ptr<TaskRunner>(new MockTaskRunner());
121   FakeUdpSocket::MockClient client;
122   std::unique_ptr<MockUdpSocketPosix> socket =
123       std::make_unique<MockUdpSocketPosix>(task_runner.get(), &client, 17,
124                                            UdpSocket::Version::kV4);
125   TestingUdpSocketReader network_waiter(mock_waiter.get());
126 
127   EXPECT_FALSE(network_waiter.IsMappedRead(socket.get()));
128   network_waiter.OnDestroy(socket.get());
129   EXPECT_FALSE(network_waiter.IsMappedRead(socket.get()));
130 
131   network_waiter.OnCreate(socket.get());
132   EXPECT_TRUE(network_waiter.IsMappedRead(socket.get()));
133 
134   network_waiter.OnDestroy(socket.get());
135   EXPECT_FALSE(network_waiter.IsMappedRead(socket.get()));
136 
137   network_waiter.OnDestroy(socket.get());
138   EXPECT_FALSE(network_waiter.IsMappedRead(socket.get()));
139 }
140 
141 }  // namespace openscreen
142