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..92087b3357a595b5afe026f00110515ce5ef2476 |
--- /dev/null |
+++ b/remoting/protocol/client_video_dispatcher_unittest.cc |
@@ -0,0 +1,180 @@ |
+// 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(); |
+ |
+ // VideoStub interface. |
+ void ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet, |
+ const base::Closure& done) override; |
+ |
+ // ChannelDispatcherBase::EventHandler interface. |
+ void OnChannelInitialized(ChannelDispatcherBase* channel_dispatcher) override; |
+ void OnChannelError(ChannelDispatcherBase* channel_dispatcher, |
+ ErrorCode error) override; |
+ |
+ protected: |
+ void OnVideoAck(scoped_ptr<VideoAck> ack, const base::Closure& done); |
+ |
+ 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_; |
+}; |
+ |
+ClientVideoDispatcherTest::ClientVideoDispatcherTest() |
+ : initialized_(false), |
+ dispatcher_(this), |
+ parser_(base::Bind(&ClientVideoDispatcherTest::OnVideoAck, |
+ base::Unretained(this)), |
+ &reader_) { |
+ 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()); |
+} |
+ |
+void ClientVideoDispatcherTest::ProcessVideoPacket( |
+ scoped_ptr<VideoPacket> video_packet, |
+ const base::Closure& done) { |
+ video_packets_.push_back(video_packet.release()); |
+ packet_done_callbacks_.push_back(done); |
+} |
+ |
+void ClientVideoDispatcherTest::OnChannelInitialized( |
+ ChannelDispatcherBase* channel_dispatcher) { |
+ initialized_ = true; |
+} |
+ |
+void ClientVideoDispatcherTest::OnChannelError( |
+ ChannelDispatcherBase* channel_dispatcher, |
+ ErrorCode error) { |
+ // Don't expect channel creation to fail. |
+ FAIL(); |
+} |
+ |
+void ClientVideoDispatcherTest::OnVideoAck(scoped_ptr<VideoAck> ack, |
+ const base::Closure& done) { |
+ ack_messages_.push_back(ack.release()); |
+ done.Run(); |
+} |
+ |
+// 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()); |
+ 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()); |
+ 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; |
+ |
+ 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 |