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..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 |