Chromium Code Reviews| Index: remoting/protocol/client_video_dispatcher_unittest.cc |
| diff --git a/remoting/protocol/client_video_dispatcher_unittest.cc b/remoting/protocol/client_video_dispatcher_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0670e6bc788ca5aba3a881329b514860a3140b5f |
| --- /dev/null |
| +++ b/remoting/protocol/client_video_dispatcher_unittest.cc |
| @@ -0,0 +1,174 @@ |
| +// 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 "base/bind.h" |
| +#include "base/memory/scoped_vector.h" |
| +#include "base/message_loop/message_loop.h" |
| +#include "base/run_loop.h" |
| +#include "remoting/base/constants.h" |
| +#include "remoting/proto/video.pb.h" |
| +#include "remoting/protocol/fake_session.h" |
| +#include "remoting/protocol/fake_stream_socket.h" |
| +#include "remoting/protocol/message_serialization.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() |
|
Wez
2015/02/11 02:22:56
nit: Move the function bodies out of the class dec
Sergey Ulanov
2015/02/17 19:37:07
Done.
|
| + : initialized_(false), |
| + dispatcher_(this), |
| + parser_(base::Bind(&ClientVideoDispatcherTest::OnVideoAck, |
| + base::Unretained(this)), |
| + &reader_) { |
| + } |
| + |
| + void Initialize() { |
| + dispatcher_.Init( |
| + &session_, |
| + ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, |
| + kDefaultStreamVersion, ChannelConfig::CODEC_UNDEFINED), |
| + this); |
| + base::RunLoop().RunUntilIdle(); |
| + DCHECK(initialized_); |
| + host_socket_.PairWith( |
| + session_.fake_channel_factory().GetFakeChannel(kVideoChannelName)); |
| + reader_.StartReading(&host_socket_); |
| + writer_.Init(&host_socket_, BufferedSocketWriter::WriteFailedCallback()); |
| + } |
| + |
| + // VideoStub interface. |
| + void ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet, |
| + const base::Closure& done) { |
| + video_packets_.push_back(video_packet.release()); |
| + packet_done_callbacks_.push_back(done); |
| + } |
| + |
| + // ChannelDispatcherBase::EventHandler interface. |
| + void OnChannelInitialized(ChannelDispatcherBase* channel_dispatcher) { |
| + initialized_ = true; |
| + } |
| + void OnChannelError(ChannelDispatcherBase* channel_dispatcher, |
| + ErrorCode error) { |
| + // Don't expect channel creation to fail. |
| + FAIL(); |
| + } |
| + |
| + protected: |
| + void OnVideoAck(scoped_ptr<VideoAck> ack, const base::Closure& done) { |
| + ack_messages_.push_back(ack.release()); |
| + done.Run(); |
| + } |
| + |
| + base::MessageLoop message_loop_; |
| + |
| + // Set to true in OnChannelInitialized(). |
| + bool initialized_; |
| + |
| + // Client side. |
| + ClientVideoDispatcher dispatcher_; |
| + FakeSession session_; |
| + |
| + // Host side. |
| + FakeStreamSocket host_socket_; |
| + MessageReader reader_; |
| + ProtobufMessageParser<VideoAck> parser_; |
| + BufferedSocketWriter writer_; |
| + |
| + ScopedVector<VideoPacket> video_packets_; |
| + std::vector<base::Closure> packet_done_callbacks_; |
| + |
| + ScopedVector<VideoAck> ack_messages_; |
| +}; |
| + |
| +// 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) { |
| + Initialize(); |
| + |
| + VideoPacket packet; |
| + packet.set_data(std::string()); |
| + |
| + // Send a VideoPacket and verify that the client receives it. |
| + writer_.Write(SerializeAndFrameMessage(packet), base::Closure()); |
| + 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; |
| + |
| + Initialize(); |
| + |
| + 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()); |
| + 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()); |
| +} |
| + |
| +// Verify that Ack messages are sent in correct order. |
| +TEST_F(ClientVideoDispatcherTest, AcksOrder) { |
| + int kTestFrameId = 3; |
| + |
| + Initialize(); |
| + |
| + VideoPacket packet; |
| + packet.set_data(std::string()); |
| + packet.set_frame_id(kTestFrameId); |
| + |
| + // Send two VideoPackets. |
| + writer_.Write(SerializeAndFrameMessage(packet), base::Closure()); |
| + base::RunLoop().RunUntilIdle(); |
| + |
| + packet.set_frame_id(kTestFrameId + 1); |
| + writer_.Write(SerializeAndFrameMessage(packet), base::Closure()); |
| + 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 |