blob: badb72b7b8959557c537ee7a8c76820243803a9f [file] [log] [blame]
// Copyright 2015 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 "remoting/protocol/client_video_dispatcher.h"
#include <memory>
#include <vector>
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "remoting/base/buffered_socket_writer.h"
#include "remoting/base/constants.h"
#include "remoting/proto/video.pb.h"
#include "remoting/protocol/fake_stream_socket.h"
#include "remoting/protocol/message_reader.h"
#include "remoting/protocol/message_serialization.h"
#include "remoting/protocol/protocol_mock_objects.h"
#include "remoting/protocol/stream_message_pipe_adapter.h"
#include "remoting/protocol/video_stub.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace remoting {
namespace protocol {
class ClientVideoDispatcherTest : public testing::Test,
public VideoStub,
public ChannelDispatcherBase::EventHandler {
public:
ClientVideoDispatcherTest();
// VideoStub interface.
void ProcessVideoPacket(std::unique_ptr<VideoPacket> video_packet,
const base::Closure& done) override;
// ChannelDispatcherBase::EventHandler interface.
void OnChannelInitialized(ChannelDispatcherBase* channel_dispatcher) override;
void OnChannelClosed(ChannelDispatcherBase* channel_dispatcher) override;
protected:
void OnChannelError(int error);
void OnMessageReceived(std::unique_ptr<CompoundBuffer> buffer);
void OnReadError(int error);
base::MessageLoop message_loop_;
// Set to true in OnChannelInitialized().
bool initialized_ = false;
// Client side.
FakeStreamChannelFactory client_channel_factory_;
StreamMessageChannelFactoryAdapter channel_factory_adapter_;
MockClientStub client_stub_;
ClientVideoDispatcher dispatcher_;
// Host side.
FakeStreamSocket host_socket_;
MessageReader reader_;
BufferedSocketWriter writer_;
std::vector<std::unique_ptr<VideoPacket>> video_packets_;
std::vector<base::Closure> packet_done_callbacks_;
std::vector<std::unique_ptr<VideoAck>> ack_messages_;
};
ClientVideoDispatcherTest::ClientVideoDispatcherTest()
: channel_factory_adapter_(
&client_channel_factory_,
base::Bind(&ClientVideoDispatcherTest::OnChannelError,
base::Unretained(this))),
dispatcher_(this, &client_stub_) {
dispatcher_.Init(&channel_factory_adapter_, this);
base::RunLoop().RunUntilIdle();
DCHECK(initialized_);
host_socket_.PairWith(
client_channel_factory_.GetFakeChannel(kVideoChannelName));
reader_.StartReading(&host_socket_,
base::Bind(&ClientVideoDispatcherTest::OnMessageReceived,
base::Unretained(this)),
base::Bind(&ClientVideoDispatcherTest::OnReadError,
base::Unretained(this)));
writer_.Start(
base::Bind(&P2PStreamSocket::Write, base::Unretained(&host_socket_)),
BufferedSocketWriter::WriteFailedCallback());
}
void ClientVideoDispatcherTest::ProcessVideoPacket(
std::unique_ptr<VideoPacket> video_packet,
const base::Closure& done) {
video_packets_.push_back(std::move(video_packet));
packet_done_callbacks_.push_back(done);
}
void ClientVideoDispatcherTest::OnChannelInitialized(
ChannelDispatcherBase* channel_dispatcher) {
initialized_ = true;
}
void ClientVideoDispatcherTest::OnChannelClosed(
ChannelDispatcherBase* channel_dispatcher) {
// Don't expect channels to be closed.
FAIL();
}
void ClientVideoDispatcherTest::OnChannelError(int error) {
// Don't expect channel creation to fail.
FAIL();
}
void ClientVideoDispatcherTest::OnMessageReceived(
std::unique_ptr<CompoundBuffer> buffer) {
std::unique_ptr<VideoAck> ack = ParseMessage<VideoAck>(buffer.get());
EXPECT_TRUE(ack);
ack_messages_.push_back(std::move(ack));
}
void ClientVideoDispatcherTest::OnReadError(int error) {
LOG(FATAL) << "Unexpected read error: " << error;
}
// Verify that the client can receive video packets and acks are not sent for
// VideoPackets that don't have frame_id field set.
TEST_F(ClientVideoDispatcherTest, WithoutAcks) {
VideoPacket packet;
packet.set_data(std::string());
// Send a VideoPacket and verify that the client receives it.
writer_.Write(SerializeAndFrameMessage(packet), base::Closure(),
TRAFFIC_ANNOTATION_FOR_TESTS);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, video_packets_.size());
packet_done_callbacks_.front().Run();
base::RunLoop().RunUntilIdle();
// Ack should never be sent for the packet without frame_id.
EXPECT_TRUE(ack_messages_.empty());
}
// Verifies that the dispatcher sends Ack message with correct rendering delay.
TEST_F(ClientVideoDispatcherTest, WithAcks) {
int kTestFrameId = 3;
VideoPacket packet;
packet.set_data(std::string());
packet.set_frame_id(kTestFrameId);
// Send a VideoPacket and verify that the client receives it.
writer_.Write(SerializeAndFrameMessage(packet), base::Closure(),
TRAFFIC_ANNOTATION_FOR_TESTS);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, video_packets_.size());
// Ack should only be sent after the packet is processed.
EXPECT_TRUE(ack_messages_.empty());
base::RunLoop().RunUntilIdle();
// Fake completion of video packet decoding, to trigger the Ack.
packet_done_callbacks_.front().Run();
base::RunLoop().RunUntilIdle();
// Verify that the Ack message has been received.
ASSERT_EQ(1U, ack_messages_.size());
EXPECT_EQ(kTestFrameId, ack_messages_[0]->frame_id());
}
// Verifies that the dispatcher properly synthesizes VideoLayout message when
// screen size changes.
TEST_F(ClientVideoDispatcherTest, VideoLayout) {
const int kScreenSize = 100;
const float kScaleFactor = 2.0;
VideoPacket packet;
packet.set_data(std::string());
packet.set_frame_id(42);
packet.mutable_format()->set_screen_width(kScreenSize);
packet.mutable_format()->set_screen_height(kScreenSize);
packet.mutable_format()->set_x_dpi(kDefaultDpi * kScaleFactor);
packet.mutable_format()->set_y_dpi(kDefaultDpi * kScaleFactor);
VideoLayout layout;
EXPECT_CALL(client_stub_, SetVideoLayout(testing::_))
.WillOnce(testing::SaveArg<0>(&layout));
// Send a VideoPacket and verify that the client receives it.
writer_.Write(SerializeAndFrameMessage(packet), base::Closure(),
TRAFFIC_ANNOTATION_FOR_TESTS);
base::RunLoop().RunUntilIdle();
ASSERT_EQ(1, layout.video_track_size());
EXPECT_EQ(0, layout.video_track(0).position_x());
EXPECT_EQ(0, layout.video_track(0).position_y());
EXPECT_EQ(kScreenSize / kScaleFactor, layout.video_track(0).width());
EXPECT_EQ(kScreenSize / kScaleFactor, layout.video_track(0).height());
EXPECT_EQ(kDefaultDpi * kScaleFactor, layout.video_track(0).x_dpi());
EXPECT_EQ(kDefaultDpi * kScaleFactor, layout.video_track(0).y_dpi());
}
// Verify that Ack messages are sent in correct order.
TEST_F(ClientVideoDispatcherTest, AcksOrder) {
int kTestFrameId = 3;
VideoPacket packet;
packet.set_data(std::string());
packet.set_frame_id(kTestFrameId);
// Send two VideoPackets.
writer_.Write(SerializeAndFrameMessage(packet), base::Closure(),
TRAFFIC_ANNOTATION_FOR_TESTS);
base::RunLoop().RunUntilIdle();
packet.set_frame_id(kTestFrameId + 1);
writer_.Write(SerializeAndFrameMessage(packet), base::Closure(),
TRAFFIC_ANNOTATION_FOR_TESTS);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2U, video_packets_.size());
EXPECT_TRUE(ack_messages_.empty());
// Call completion callbacks in revers order.
packet_done_callbacks_[1].Run();
packet_done_callbacks_[0].Run();
base::RunLoop().RunUntilIdle();
// Verify order of Ack messages.
ASSERT_EQ(2U, ack_messages_.size());
EXPECT_EQ(kTestFrameId, ack_messages_[0]->frame_id());
EXPECT_EQ(kTestFrameId + 1, ack_messages_[1]->frame_id());
}
} // namespace protocol
} // namespace remoting