blob: 47247fc7e380087157529d3b20cc749417201ba7 [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 "api/public/presentation/presentation_controller.h"
#include <string>
#include <vector>
#include "api/impl/quic/testing/quic_test_support.h"
#include "api/impl/service_listener_impl.h"
#include "api/impl/testing/fake_clock.h"
#include "api/public/message_demuxer.h"
#include "api/public/network_service_manager.h"
#include "api/public/testing/message_demuxer_test_support.h"
#include "third_party/googletest/src/googlemock/include/gmock/gmock.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
namespace openscreen {
namespace presentation {
using std::chrono::seconds;
using ::testing::_;
using ::testing::Invoke;
constexpr char kTestUrl[] = "https://example.foo";
class MockServiceListenerDelegate final : public ServiceListenerImpl::Delegate {
public:
~MockServiceListenerDelegate() override = default;
ServiceListenerImpl* listener() { return listener_; }
MOCK_METHOD0(StartListener, void());
MOCK_METHOD0(StartAndSuspendListener, void());
MOCK_METHOD0(StopListener, void());
MOCK_METHOD0(SuspendListener, void());
MOCK_METHOD0(ResumeListener, void());
MOCK_METHOD1(SearchNow, void(ServiceListener::State from));
};
class MockReceiverObserver final : public ReceiverObserver {
public:
~MockReceiverObserver() override = default;
MOCK_METHOD2(OnRequestFailed,
void(const std::string& presentation_url,
const std::string& service_id));
MOCK_METHOD2(OnReceiverAvailable,
void(const std::string& presentation_url,
const std::string& service_id));
MOCK_METHOD2(OnReceiverUnavailable,
void(const std::string& presentation_url,
const std::string& service_id));
};
class ControllerTest : public ::testing::Test {
protected:
void SetUp() override {
auto service_listener =
std::make_unique<ServiceListenerImpl>(&mock_listener_delegate_);
NetworkServiceManager::Create(std::move(service_listener), nullptr,
std::move(quic_bridge_.quic_client),
std::move(quic_bridge_.quic_server));
controller_ = std::make_unique<Controller>(FakeClock::now);
ON_CALL(quic_bridge_.mock_server_observer, OnIncomingConnectionMock(_))
.WillByDefault(
Invoke([this](std::unique_ptr<ProtocolConnection>& connection) {
controller_endpoint_id_ = connection->endpoint_id();
}));
availability_watch_ =
quic_bridge_.receiver_demuxer->SetDefaultMessageTypeWatch(
msgs::Type::kPresentationUrlAvailabilityRequest, &mock_callback_);
}
void TearDown() override {
availability_watch_ = MessageDemuxer::MessageWatch();
controller_.reset();
NetworkServiceManager::Dispose();
}
void ExpectAvailabilityRequest(
MockMessageCallback* mock_callback,
msgs::PresentationUrlAvailabilityRequest* request) {
EXPECT_CALL(*mock_callback, OnStreamMessage(_, _, _, _, _, _))
.WillOnce(Invoke([request](uint64_t endpoint_id, uint64_t cid,
msgs::Type message_type,
const uint8_t* buffer, size_t buffer_size,
platform::Clock::time_point now) {
ssize_t result = msgs::DecodePresentationUrlAvailabilityRequest(
buffer, buffer_size, request);
return result;
}));
}
void SendAvailabilityResponse(
const msgs::PresentationUrlAvailabilityResponse& response) {
std::unique_ptr<ProtocolConnection> controller_connection =
NetworkServiceManager::Get()
->GetProtocolConnectionServer()
->CreateProtocolConnection(controller_endpoint_id_);
ASSERT_TRUE(controller_connection);
ASSERT_EQ(Error::Code::kNone,
controller_connection
->WriteMessage(
response, msgs::EncodePresentationUrlAvailabilityResponse)
.code());
}
void SendAvailabilityEvent(
const msgs::PresentationUrlAvailabilityEvent& event) {
std::unique_ptr<ProtocolConnection> controller_connection =
NetworkServiceManager::Get()
->GetProtocolConnectionServer()
->CreateProtocolConnection(controller_endpoint_id_);
ASSERT_TRUE(controller_connection);
ASSERT_EQ(
Error::Code::kNone,
controller_connection
->WriteMessage(event, msgs::EncodePresentationUrlAvailabilityEvent)
.code());
}
MessageDemuxer::MessageWatch availability_watch_;
MockMessageCallback mock_callback_;
FakeClock fake_clock_{platform::Clock::time_point(seconds(11111))};
FakeQuicBridge quic_bridge_{FakeClock::now};
MockServiceListenerDelegate mock_listener_delegate_;
std::unique_ptr<Controller> controller_;
ServiceInfo receiver_info1{"service-id1",
"lucas-auer",
1,
quic_bridge_.kReceiverEndpoint,
{}};
MockReceiverObserver mock_receiver_observer_;
uint64_t controller_endpoint_id_{0};
};
TEST_F(ControllerTest, ReceiverWatchMoves) {
std::vector<std::string> urls{"one fish", "two fish", "red fish", "gnu fish"};
MockReceiverObserver mock_observer;
Controller::ReceiverWatch watch1(controller_.get(), urls, &mock_observer);
EXPECT_TRUE(watch1);
Controller::ReceiverWatch watch2;
EXPECT_FALSE(watch2);
watch2 = std::move(watch1);
EXPECT_FALSE(watch1);
EXPECT_TRUE(watch2);
Controller::ReceiverWatch watch3(std::move(watch2));
EXPECT_FALSE(watch2);
EXPECT_TRUE(watch3);
}
TEST_F(ControllerTest, ConnectRequestMoves) {
std::string service_id{"service-id1"};
uint64_t request_id = 7;
Controller::ConnectRequest request1(controller_.get(), service_id, false,
request_id);
EXPECT_TRUE(request1);
Controller::ConnectRequest request2;
EXPECT_FALSE(request2);
request2 = std::move(request1);
EXPECT_FALSE(request1);
EXPECT_TRUE(request2);
Controller::ConnectRequest request3(std::move(request2));
EXPECT_FALSE(request2);
EXPECT_TRUE(request3);
}
TEST_F(ControllerTest, ReceiverAvailable) {
mock_listener_delegate_.listener()->OnReceiverAdded(receiver_info1);
Controller::ReceiverWatch watch =
controller_->RegisterReceiverWatch({kTestUrl}, &mock_receiver_observer_);
msgs::PresentationUrlAvailabilityRequest request;
ExpectAvailabilityRequest(&mock_callback_, &request);
quic_bridge_.RunTasksUntilIdle();
msgs::PresentationUrlAvailabilityResponse response;
response.request_id = request.request_id;
response.url_availabilities.push_back(msgs::UrlAvailability::kAvailable);
SendAvailabilityResponse(response);
EXPECT_CALL(mock_receiver_observer_, OnReceiverAvailable(_, _));
quic_bridge_.RunTasksUntilIdle();
MockReceiverObserver mock_receiver_observer2;
EXPECT_CALL(mock_receiver_observer2, OnReceiverAvailable(_, _));
Controller::ReceiverWatch watch2 =
controller_->RegisterReceiverWatch({kTestUrl}, &mock_receiver_observer2);
}
TEST_F(ControllerTest, ReceiverWatchCancel) {
mock_listener_delegate_.listener()->OnReceiverAdded(receiver_info1);
Controller::ReceiverWatch watch =
controller_->RegisterReceiverWatch({kTestUrl}, &mock_receiver_observer_);
msgs::PresentationUrlAvailabilityRequest request;
ExpectAvailabilityRequest(&mock_callback_, &request);
quic_bridge_.RunTasksUntilIdle();
msgs::PresentationUrlAvailabilityResponse response;
response.request_id = request.request_id;
response.url_availabilities.push_back(msgs::UrlAvailability::kAvailable);
SendAvailabilityResponse(response);
EXPECT_CALL(mock_receiver_observer_, OnReceiverAvailable(_, _));
quic_bridge_.RunTasksUntilIdle();
MockReceiverObserver mock_receiver_observer2;
EXPECT_CALL(mock_receiver_observer2, OnReceiverAvailable(_, _));
Controller::ReceiverWatch watch2 =
controller_->RegisterReceiverWatch({kTestUrl}, &mock_receiver_observer2);
watch = Controller::ReceiverWatch();
msgs::PresentationUrlAvailabilityEvent event;
event.watch_id = request.watch_id;
event.url_availabilities.push_back(msgs::UrlAvailability::kUnavailable);
EXPECT_CALL(mock_receiver_observer2, OnReceiverUnavailable(_, _));
EXPECT_CALL(mock_receiver_observer_, OnReceiverUnavailable(_, _)).Times(0);
SendAvailabilityEvent(event);
quic_bridge_.RunTasksUntilIdle();
}
} // namespace presentation
} // namespace openscreen