xref: /aosp_15_r20/external/openscreen/osp/impl/presentation/presentation_receiver_unittest.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
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 "osp/public/presentation/presentation_receiver.h"
6 
7 #include <memory>
8 
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
11 #include "osp/impl/presentation/testing/mock_connection_delegate.h"
12 #include "osp/impl/quic/quic_client.h"
13 #include "osp/impl/quic/quic_server.h"
14 #include "osp/impl/quic/testing/fake_quic_connection_factory.h"
15 #include "osp/impl/quic/testing/quic_test_support.h"
16 #include "osp/public/network_service_manager.h"
17 #include "osp/public/protocol_connection_server.h"
18 #include "osp/public/testing/message_demuxer_test_support.h"
19 #include "platform/test/fake_clock.h"
20 #include "platform/test/fake_task_runner.h"
21 
22 namespace openscreen {
23 namespace osp {
24 
25 namespace {
26 
27 using ::testing::_;
28 using ::testing::Invoke;
29 using ::testing::NiceMock;
30 
31 class MockConnectRequest final
32     : public ProtocolConnectionClient::ConnectionRequestCallback {
33  public:
34   ~MockConnectRequest() override = default;
35 
36   MOCK_METHOD2(OnConnectionOpened,
37                void(uint64_t request_id,
38                     std::unique_ptr<ProtocolConnection> connection));
39   MOCK_METHOD1(OnConnectionFailed, void(uint64_t request_id));
40 };
41 
42 class MockReceiverDelegate final : public ReceiverDelegate {
43  public:
44   ~MockReceiverDelegate() override = default;
45 
46   MOCK_METHOD3(
47       OnUrlAvailabilityRequest,
48       std::vector<msgs::UrlAvailability>(uint64_t watch_id,
49                                          uint64_t watch_duration,
50                                          std::vector<std::string> urls));
51   MOCK_METHOD3(StartPresentation,
52                bool(const Connection::PresentationInfo& info,
53                     uint64_t source_id,
54                     const std::vector<msgs::HttpHeader>& http_headers));
55   MOCK_METHOD3(ConnectToPresentation,
56                bool(uint64_t request_id,
57                     const std::string& id,
58                     uint64_t source_id));
59   MOCK_METHOD2(TerminatePresentation,
60                void(const std::string& id, TerminationReason reason));
61 };
62 
63 class PresentationReceiverTest : public ::testing::Test {
64  public:
PresentationReceiverTest()65   PresentationReceiverTest() {
66     fake_clock_ = std::make_unique<FakeClock>(
67         Clock::time_point(std::chrono::milliseconds(1298424)));
68     task_runner_ = std::make_unique<FakeTaskRunner>(fake_clock_.get());
69     quic_bridge_ =
70         std::make_unique<FakeQuicBridge>(task_runner_.get(), FakeClock::now);
71   }
72 
73  protected:
MakeClientStream()74   std::unique_ptr<ProtocolConnection> MakeClientStream() {
75     MockConnectRequest mock_connect_request;
76     NetworkServiceManager::Get()->GetProtocolConnectionClient()->Connect(
77         quic_bridge_->kReceiverEndpoint, &mock_connect_request);
78     std::unique_ptr<ProtocolConnection> stream;
79     EXPECT_CALL(mock_connect_request, OnConnectionOpened(_, _))
80         .WillOnce([&stream](uint64_t request_id,
81                             std::unique_ptr<ProtocolConnection> connection) {
82           stream = std::move(connection);
83         });
84     quic_bridge_->RunTasksUntilIdle();
85     return stream;
86   }
87 
SetUp()88   void SetUp() override {
89     NetworkServiceManager::Create(nullptr, nullptr,
90                                   std::move(quic_bridge_->quic_client),
91                                   std::move(quic_bridge_->quic_server));
92     Receiver::Get()->Init();
93     Receiver::Get()->SetReceiverDelegate(&mock_receiver_delegate_);
94   }
95 
TearDown()96   void TearDown() override {
97     Receiver::Get()->SetReceiverDelegate(nullptr);
98     Receiver::Get()->Deinit();
99     NetworkServiceManager::Dispose();
100   }
101 
102   std::unique_ptr<FakeClock> fake_clock_;
103   std::unique_ptr<FakeTaskRunner> task_runner_;
104   const std::string url1_{"https://www.example.com/receiver.html"};
105   std::unique_ptr<FakeQuicBridge> quic_bridge_;
106   MockReceiverDelegate mock_receiver_delegate_;
107 };
108 
109 }  // namespace
110 
111 // TODO(btolsch): Availability CL includes watch duration, so when that lands,
112 // also test proper updating here.
TEST_F(PresentationReceiverTest,QueryAvailability)113 TEST_F(PresentationReceiverTest, QueryAvailability) {
114   MockMessageCallback mock_callback;
115   MessageDemuxer::MessageWatch availability_watch =
116       quic_bridge_->controller_demuxer->SetDefaultMessageTypeWatch(
117           msgs::Type::kPresentationUrlAvailabilityResponse, &mock_callback);
118 
119   std::unique_ptr<ProtocolConnection> stream = MakeClientStream();
120   ASSERT_TRUE(stream);
121 
122   msgs::PresentationUrlAvailabilityRequest request{/* .request_id = */ 0,
123                                                    /* .urls = */ {url1_},
124                                                    /* .watch_duration = */ 0,
125                                                    /* .watch_id = */ 0};
126   msgs::CborEncodeBuffer buffer;
127   ASSERT_TRUE(msgs::EncodePresentationUrlAvailabilityRequest(request, &buffer));
128   stream->Write(buffer.data(), buffer.size());
129 
130   EXPECT_CALL(mock_receiver_delegate_, OnUrlAvailabilityRequest(_, _, _))
131       .WillOnce(Invoke([this](uint64_t watch_id, uint64_t watch_duration,
132                               std::vector<std::string> urls) {
133         EXPECT_EQ(std::vector<std::string>{url1_}, urls);
134 
135         return std::vector<msgs::UrlAvailability>{
136             msgs::UrlAvailability::kAvailable};
137       }));
138 
139   msgs::PresentationUrlAvailabilityResponse response;
140   EXPECT_CALL(mock_callback, OnStreamMessage(_, _, _, _, _, _))
141       .WillOnce(
142           Invoke([&response](uint64_t endpoint_id, uint64_t cid,
143                              msgs::Type message_type, const uint8_t* buffer,
144                              size_t buffer_size, Clock::time_point now) {
145             ssize_t result = msgs::DecodePresentationUrlAvailabilityResponse(
146                 buffer, buffer_size, &response);
147             return result;
148           }));
149   quic_bridge_->RunTasksUntilIdle();
150   EXPECT_EQ(request.request_id, response.request_id);
151   EXPECT_EQ(
152       (std::vector<msgs::UrlAvailability>{msgs::UrlAvailability::kAvailable}),
153       response.url_availabilities);
154 }
155 
TEST_F(PresentationReceiverTest,StartPresentation)156 TEST_F(PresentationReceiverTest, StartPresentation) {
157   MockMessageCallback mock_callback;
158   MessageDemuxer::MessageWatch initiation_watch =
159       quic_bridge_->controller_demuxer->SetDefaultMessageTypeWatch(
160           msgs::Type::kPresentationStartResponse, &mock_callback);
161 
162   std::unique_ptr<ProtocolConnection> stream = MakeClientStream();
163   ASSERT_TRUE(stream);
164 
165   const std::string presentation_id = "KMvyNqTCvvSv7v5X";
166   msgs::PresentationStartRequest request;
167   request.request_id = 0;
168   request.presentation_id = presentation_id;
169   request.url = url1_;
170   request.headers = {msgs::HttpHeader{"Accept-Language", "de"}};
171   msgs::CborEncodeBuffer buffer;
172   ASSERT_TRUE(msgs::EncodePresentationStartRequest(request, &buffer));
173   stream->Write(buffer.data(), buffer.size());
174   Connection::PresentationInfo info;
175   EXPECT_CALL(mock_receiver_delegate_, StartPresentation(_, _, request.headers))
176       .WillOnce(::testing::DoAll(::testing::SaveArg<0>(&info),
177                                  ::testing::Return(true)));
178   quic_bridge_->RunTasksUntilIdle();
179   EXPECT_EQ(presentation_id, info.id);
180   EXPECT_EQ(url1_, info.url);
181 
182   NiceMock<MockConnectionDelegate> null_connection_delegate;
183   Connection connection(Connection::PresentationInfo{presentation_id, url1_},
184                         &null_connection_delegate, Receiver::Get());
185   Receiver::Get()->OnPresentationStarted(presentation_id, &connection,
186                                          ResponseResult::kSuccess);
187   msgs::PresentationStartResponse response;
188   EXPECT_CALL(mock_callback, OnStreamMessage(_, _, _, _, _, _))
189       .WillOnce(
190           Invoke([&response](uint64_t endpoint_id, uint64_t cid,
191                              msgs::Type message_type, const uint8_t* buffer,
192                              size_t buffer_size, Clock::time_point now) {
193             ssize_t result = msgs::DecodePresentationStartResponse(
194                 buffer, buffer_size, &response);
195             return result;
196           }));
197   quic_bridge_->RunTasksUntilIdle();
198   EXPECT_EQ(msgs::Result::kSuccess, response.result);
199   EXPECT_EQ(connection.connection_id(), response.connection_id);
200 }
201 
202 // TODO(btolsch): Connect and reconnect.
203 // TODO(btolsch): Terminate request and event.
204 
205 }  // namespace osp
206 }  // namespace openscreen
207