// Copyright 2013 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 "base/test/simple_test_tick_clock.h" #include "media/cast/pacing/paced_sender.h" #include "media/cast/test/fake_task_runner.h" #include "testing/gmock/include/gmock/gmock.h" namespace media { namespace cast { using testing::_; static const uint8 kValue = 123; static const size_t kSize1 = 100; static const size_t kSize2 = 101; static const size_t kSize3 = 102; static const size_t kSize4 = 103; static const size_t kNackSize = 104; static const int64 kStartMillisecond = GG_INT64_C(12345678900000); class TestPacketSender : public PacketSender { public: virtual bool SendPackets(const PacketList& packets) OVERRIDE { PacketList::const_iterator it = packets.begin(); for (; it != packets.end(); ++it) { EXPECT_FALSE(expected_packet_size_.empty()); size_t expected_packet_size = expected_packet_size_.front(); expected_packet_size_.pop_front(); EXPECT_EQ(expected_packet_size, it->size()); } return true; } virtual bool SendPacket(const Packet& packet) OVERRIDE { return true; } void AddExpectedSize(int expected_packet_size, int repeat_count) { for (int i = 0; i < repeat_count; ++i) { expected_packet_size_.push_back(expected_packet_size); } } private: std::list expected_packet_size_; }; class PacedSenderTest : public ::testing::Test { protected: PacedSenderTest() { testing_clock_.Advance( base::TimeDelta::FromMilliseconds(kStartMillisecond)); } virtual ~PacedSenderTest() {} virtual void SetUp() { task_runner_ = new test::FakeTaskRunner(&testing_clock_); cast_environment_ = new CastEnvironment(&testing_clock_, task_runner_, task_runner_, task_runner_, task_runner_, task_runner_); paced_sender_.reset(new PacedSender(cast_environment_, &mock_transport_)); } PacketList CreatePacketList(size_t packet_size, int num_of_packets_in_frame) { PacketList packets; for (int i = 0; i < num_of_packets_in_frame; ++i) { packets.push_back(Packet(packet_size, kValue)); } return packets; } base::SimpleTestTickClock testing_clock_; TestPacketSender mock_transport_; scoped_refptr task_runner_; scoped_ptr paced_sender_; scoped_refptr cast_environment_; }; TEST_F(PacedSenderTest, PassThroughRtcp) { mock_transport_.AddExpectedSize(kSize1, 1); PacketList packets = CreatePacketList(kSize1, 1); EXPECT_TRUE(paced_sender_->SendPackets(packets)); EXPECT_TRUE(paced_sender_->ResendPackets(packets)); mock_transport_.AddExpectedSize(kSize2, 1); EXPECT_TRUE(paced_sender_->SendRtcpPacket(Packet(kSize2, kValue))); } TEST_F(PacedSenderTest, BasicPace) { int num_of_packets = 9; PacketList packets = CreatePacketList(kSize1, num_of_packets); mock_transport_.AddExpectedSize(kSize1, 3); EXPECT_TRUE(paced_sender_->SendPackets(packets)); // Check that we get the next burst. mock_transport_.AddExpectedSize(kSize1, 3); base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(10); testing_clock_.Advance(timeout); task_runner_->RunTasks(); // If we call process too early make sure we don't send any packets. timeout = base::TimeDelta::FromMilliseconds(5); testing_clock_.Advance(timeout); task_runner_->RunTasks(); // Check that we get the next burst. mock_transport_.AddExpectedSize(kSize1, 3); testing_clock_.Advance(timeout); task_runner_->RunTasks(); // Check that we don't get any more packets. testing_clock_.Advance(timeout); task_runner_->RunTasks(); } TEST_F(PacedSenderTest, PaceWithNack) { // Testing what happen when we get multiple NACK requests for a fully lost // frames just as we sent the first packets in a frame. int num_of_packets_in_frame = 9; int num_of_packets_in_nack = 9; PacketList first_frame_packets = CreatePacketList(kSize1, num_of_packets_in_frame); PacketList second_frame_packets = CreatePacketList(kSize2, num_of_packets_in_frame); PacketList nack_packets = CreatePacketList(kNackSize, num_of_packets_in_nack); // Check that the first burst of the frame go out on the wire. mock_transport_.AddExpectedSize(kSize1, 3); EXPECT_TRUE(paced_sender_->SendPackets(first_frame_packets)); // Add first NACK request. EXPECT_TRUE(paced_sender_->ResendPackets(nack_packets)); // Check that we get the first NACK burst. mock_transport_.AddExpectedSize(kNackSize, 5); base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(10); testing_clock_.Advance(timeout); task_runner_->RunTasks(); // Add second NACK request. EXPECT_TRUE(paced_sender_->ResendPackets(nack_packets)); // Check that we get the next NACK burst. mock_transport_.AddExpectedSize(kNackSize, 7); testing_clock_.Advance(timeout); task_runner_->RunTasks(); // End of NACK plus a packet from the oldest frame. mock_transport_.AddExpectedSize(kNackSize, 6); mock_transport_.AddExpectedSize(kSize1, 1); testing_clock_.Advance(timeout); task_runner_->RunTasks(); // Add second frame. // Make sure we don't delay the second frame due to the previous packets. EXPECT_TRUE(paced_sender_->SendPackets(second_frame_packets)); // Last packets of frame 1 and the first packets of frame 2. mock_transport_.AddExpectedSize(kSize1, 5); mock_transport_.AddExpectedSize(kSize2, 2); testing_clock_.Advance(timeout); task_runner_->RunTasks(); // Last packets of frame 2. mock_transport_.AddExpectedSize(kSize2, 7); testing_clock_.Advance(timeout); task_runner_->RunTasks(); // No more packets. testing_clock_.Advance(timeout); task_runner_->RunTasks(); } TEST_F(PacedSenderTest, PaceWith60fps) { // Testing what happen when we get multiple NACK requests for a fully lost // frames just as we sent the first packets in a frame. int num_of_packets_in_frame = 9; PacketList first_frame_packets = CreatePacketList(kSize1, num_of_packets_in_frame); PacketList second_frame_packets = CreatePacketList(kSize2, num_of_packets_in_frame); PacketList third_frame_packets = CreatePacketList(kSize3, num_of_packets_in_frame); PacketList fourth_frame_packets = CreatePacketList(kSize4, num_of_packets_in_frame); base::TimeDelta timeout_10ms = base::TimeDelta::FromMilliseconds(10); // Check that the first burst of the frame go out on the wire. mock_transport_.AddExpectedSize(kSize1, 3); EXPECT_TRUE(paced_sender_->SendPackets(first_frame_packets)); mock_transport_.AddExpectedSize(kSize1, 3); testing_clock_.Advance(timeout_10ms); task_runner_->RunTasks(); testing_clock_.Advance(base::TimeDelta::FromMilliseconds(6)); // Add second frame, after 16 ms. EXPECT_TRUE(paced_sender_->SendPackets(second_frame_packets)); testing_clock_.Advance(base::TimeDelta::FromMilliseconds(4)); mock_transport_.AddExpectedSize(kSize1, 3); mock_transport_.AddExpectedSize(kSize2, 1); testing_clock_.Advance(timeout_10ms); task_runner_->RunTasks(); mock_transport_.AddExpectedSize(kSize2, 4); testing_clock_.Advance(timeout_10ms); task_runner_->RunTasks(); testing_clock_.Advance(base::TimeDelta::FromMilliseconds(3)); // Add third frame, after 33 ms. EXPECT_TRUE(paced_sender_->SendPackets(third_frame_packets)); mock_transport_.AddExpectedSize(kSize2, 4); mock_transport_.AddExpectedSize(kSize3, 1); testing_clock_.Advance(base::TimeDelta::FromMilliseconds(7)); task_runner_->RunTasks(); // Add fourth frame, after 50 ms. EXPECT_TRUE(paced_sender_->SendPackets(fourth_frame_packets)); mock_transport_.AddExpectedSize(kSize3, 6); testing_clock_.Advance(timeout_10ms); task_runner_->RunTasks(); mock_transport_.AddExpectedSize(kSize3, 2); mock_transport_.AddExpectedSize(kSize4, 4); testing_clock_.Advance(timeout_10ms); task_runner_->RunTasks(); mock_transport_.AddExpectedSize(kSize4, 5); testing_clock_.Advance(timeout_10ms); task_runner_->RunTasks(); testing_clock_.Advance(timeout_10ms); task_runner_->RunTasks(); } } // namespace cast } // namespace media