Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1143)

Unified Diff: remoting/protocol/client_video_dispatcher_unittest.cc

Issue 850983002: Implement video frame acknowledgements in the chromoting protocol. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..7a1a01f44fadc22196efa140383c81bc51ca9842
--- /dev/null
+++ b/remoting/protocol/client_video_dispatcher_unittest.cc
@@ -0,0 +1,221 @@
+// 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/message_loop/message_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/gmock/include/gmock/gmock.h"
+
+using testing::_;
+
+namespace remoting {
+namespace protocol {
+
+class MockChannelEventHandler : public ChannelDispatcherBase::EventHandler {
+ public:
+ MockChannelEventHandler() {}
+ ~MockChannelEventHandler() override {}
+
+ MOCK_METHOD1(OnChannelInitialized,
+ void(ChannelDispatcherBase* channel_dispatcher));
+ MOCK_METHOD2(OnChannelError,
+ void(ChannelDispatcherBase* channel_dispatcher,
+ ErrorCode error));
+};
+
+class ClientVideoDispatcherTest : public testing::Test, public VideoStub {
+ public:
+ ClientVideoDispatcherTest()
+ : dispatcher_(this),
+ parser_(base::Bind(&ClientVideoDispatcherTest::OnVideoAck,
+ base::Unretained(this)),
+ &reader_) {}
+
+ void Initialize(int version) {
Wez 2015/01/21 01:35:39 nit: InitializeWithProtocolVersion?
Sergey Ulanov 2015/01/29 01:33:28 Done.
+ EXPECT_CALL(event_handler_, OnChannelInitialized(_));
Wez 2015/01/21 01:35:39 Having this expectation in here immediately follow
Sergey Ulanov 2015/01/29 01:33:28 Done.
+ dispatcher_.Init(&session_,
+ ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, version,
+ ChannelConfig::CODEC_UNDEFINED),
+ &event_handler_);
+ message_loop_.RunUntilIdle();
+ 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) {
Wez 2015/01/21 01:35:39 Why is ChannelEventHandler a mock but VideoStub a
Sergey Ulanov 2015/01/29 01:33:29 Removed MockChannelEventHandler.
+ video_packet_ = video_packet.Pass();
+ packet_processed_closure_ = done;
+ }
+
+ protected:
+ void OnVideoAck(scoped_ptr<VideoAck> ack, const base::Closure& done) {
+ ack_message_ = ack.Pass();
+ done.Run();
+ }
+
+ base::MessageLoop message_loop_;
+
+ MockChannelEventHandler event_handler_;
+ ClientVideoDispatcher dispatcher_;
+ FakeSession session_;
+ FakeStreamSocket host_socket_;
+ MessageReader reader_;
+ ProtobufMessageParser<VideoAck> parser_;
+ BufferedSocketWriter writer_;
Wez 2015/01/21 01:35:39 nit: Can you break these up a bit to separate out
Sergey Ulanov 2015/01/29 01:33:29 Done.
+
+ scoped_ptr<VideoPacket> video_packet_;
+ base::Closure packet_processed_closure_;
+
+ scoped_ptr<VideoAck> ack_message_;
+};
+
+// Verify that acks are not sent for older versions of the protocol.
+TEST_F(ClientVideoDispatcherTest, WithoutAcks) {
Wez 2015/01/21 01:35:39 nit: Add a basic test to verify just that parsed V
Sergey Ulanov 2015/01/29 01:33:28 This test already verifies it. Updated the comment
+ int kTestFrameId = 3;
+
+ Initialize(kDefaultStreamVersion);
+
+ 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());
+ message_loop_.RunUntilIdle();
Wez 2015/01/21 01:35:39 IIUC the New Way is: RunLoop().RunUntilIdle() fo
Sergey Ulanov 2015/01/29 01:33:28 Done.
+ ASSERT_TRUE(video_packet_);
Wez 2015/01/21 01:35:39 EXPECT_TRUE
Sergey Ulanov 2015/01/29 01:33:28 Done.
+
+ packet_processed_closure_.Run();
+ message_loop_.RunUntilIdle();
+
+ // Ack should never be sent for this version of the protocol.
+ ASSERT_FALSE(ack_message_);
Wez 2015/01/21 01:35:39 EXPECT_FALSE
Sergey Ulanov 2015/01/29 01:33:29 Done.
+}
+
+// Verifies that the dispatchers sends Ack message with correct rendering delay.
Wez 2015/01/21 01:35:39 s/dispatchers/dispatcher
Sergey Ulanov 2015/01/29 01:33:28 Done.
+TEST_F(ClientVideoDispatcherTest, WithAcks) {
+ int kTestFrameId = 3;
+
+ Initialize(kVideoWithAckStreamVersion);
+
+ VideoPacket packet;
+ packet.set_data(std::string());
+ packet.set_frame_id(kTestFrameId);
+
+ // Send a VideoPacket and verify that the client receives it.
+ base::TimeTicks write_started_time = base::TimeTicks::Now();
+ writer_.Write(SerializeAndFrameMessage(packet), base::Closure());
+ message_loop_.RunUntilIdle();
+ ASSERT_TRUE(video_packet_);
Wez 2015/01/21 01:35:39 EXPECT_TRUE
Sergey Ulanov 2015/01/29 01:33:28 Done.
+
+ // Ack should only be sent after the packet is processed.
+ ASSERT_FALSE(ack_message_);
+
+ // Simulate frame render delay.
+ base::TimeTicks render_started_time = base::TimeTicks::Now();
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
+ base::TimeDelta render_delay_min =
+ base::TimeTicks::Now() - render_started_time;
+
+ packet_processed_closure_.Run();
Wez 2015/01/21 01:35:39 Comment this, e.g. "Fake completion of video packe
Sergey Ulanov 2015/01/29 01:33:28 Done.
+ base::TimeDelta render_delay_max =
+ base::TimeTicks::Now() - write_started_time;
Wez 2015/01/21 01:35:39 nit: Could we use a base::TickTimer "seam" to allo
Sergey Ulanov 2015/01/29 01:33:29 There are two problems with base::TickClock 1. It'
+
+ message_loop_.RunUntilIdle();
+ ASSERT_TRUE(ack_message_);
+ EXPECT_EQ(kTestFrameId, ack_message_->frame_id());
+
+ // Verify that rendering latency is reported correctly.
+ base::TimeDelta render_delay =
+ base::TimeDelta::FromMicroseconds(ack_message_->rendering_delay_us());
+ EXPECT_TRUE(render_delay >= render_delay_min);
+ EXPECT_TRUE(render_delay <= render_delay_max);
+}
+
+// Verifies that the dispatcher reports correct read delay in the messages it
+// receives.
+TEST_F(ClientVideoDispatcherTest, ReadDelay) {
+ int kTestFrameId = 3;
+
+ Initialize(kVideoWithAckStreamVersion);
+
+ VideoPacket packet;
+ packet.set_data(std::string());
+ packet.set_frame_id(kTestFrameId);
+
+ // Generate buffers for two video frames.
+ scoped_refptr<net::IOBufferWithSize> packet_buffer_1 =
+ SerializeAndFrameMessage(packet);
+ packet.set_frame_id(kTestFrameId + 1);
+ scoped_refptr<net::IOBufferWithSize> packet_buffer_2 =
+ SerializeAndFrameMessage(packet);
+
+ base::TimeTicks send_started_time = base::TimeTicks::Now();
+
+ // First send all data for the first frame and the first byte for the second
+ // one in a single network packet.
Wez 2015/01/21 01:35:39 nit: There's no guarantee that this will result in
Wez 2015/01/21 01:35:39 nit: s/one/frame
Sergey Ulanov 2015/01/29 01:33:29 Done.
Sergey Ulanov 2015/01/29 01:33:29 I think we can make this assumption with the fake
+ scoped_refptr<net::IOBufferWithSize> buffer =
+ new net::IOBufferWithSize(packet_buffer_1->size() + 1);
+ memcpy(buffer->data(), packet_buffer_1->data(), packet_buffer_1->size());
+ memcpy(buffer->data() + packet_buffer_1->size(), packet_buffer_2->data(), 1);
+ writer_.Write(buffer, base::Closure());
+ message_loop_.RunUntilIdle();
+
+ // Verify that the packet was received.
+ ASSERT_TRUE(video_packet_);
Wez 2015/01/21 01:35:39 nit: EXPECT_TRUE here
Sergey Ulanov 2015/01/29 01:33:28 Done.
+ video_packet_.reset();
+ packet_processed_closure_.Run();
+ message_loop_.RunUntilIdle();
+
+ // Verify that the Ack message for the first video frame has time_to_receive
+ // field set to 0, because the whole frame was received in one message.
Wez 2015/01/21 01:35:39 Doesn't that make this test susceptible to flake e
Sergey Ulanov 2015/01/29 01:33:28 No. It's not possible with the current implementat
+ ASSERT_TRUE(ack_message_);
+ EXPECT_EQ(kTestFrameId, ack_message_->frame_id());
+ EXPECT_EQ(0, ack_message_->time_to_receive_us());
+ ack_message_.reset();
+
+ // Simulate networking latency while receiving the second frame.
+ base::TimeTicks network_delay_started_time = base::TimeTicks::Now();
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
+ base::TimeDelta time_to_receive_min =
+ base::TimeTicks::Now() - network_delay_started_time;
+
+ // Send the remainder of the second frame.
+ buffer = new net::IOBufferWithSize(packet_buffer_2->size() - 1);
+ memcpy(buffer->data(), packet_buffer_2->data() + 1,
+ packet_buffer_2->size() - 1);
+ writer_.Write(buffer, base::Closure());
+ message_loop_.RunUntilIdle();
+
+ // Verify that the second packet was received.
+ ASSERT_TRUE(video_packet_);
Wez 2015/01/21 01:35:39 nit: EXPECT_TRUE
Sergey Ulanov 2015/01/29 01:33:28 Done.
+ video_packet_.reset();
Wez 2015/01/21 01:35:39 Do you need to reset it here? You're not touching
Sergey Ulanov 2015/01/29 01:33:29 Done.
+ packet_processed_closure_.Run();
+ message_loop_.RunUntilIdle();
+
+ // Verify that we've received Ack for the second frame.
+ ASSERT_TRUE(ack_message_);
+ EXPECT_EQ(kTestFrameId + 1, ack_message_->frame_id());
+
+ // Verify that the dispatcher set correct time_to_receive value.
+ base::TimeDelta time_to_receive =
+ base::TimeDelta::FromMicroseconds(ack_message_->time_to_receive_us());
+ base::TimeDelta time_to_receive_max =
+ base::TimeTicks::Now() - send_started_time;
Wez 2015/01/21 01:35:39 nit: Shouldn't this calculation take place immedia
Sergey Ulanov 2015/01/29 01:33:28 Done.
+ EXPECT_TRUE(time_to_receive >= time_to_receive_min);
+ EXPECT_TRUE(time_to_receive <= time_to_receive_max);
+}
+
+} // namespace protocol
+} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698