/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/call.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/test/fake_network_pipe.h" using ::testing::_; using ::testing::AnyNumber; using ::testing::Return; using ::testing::Invoke; namespace webrtc { class MockReceiver : public PacketReceiver { public: MockReceiver() {} virtual ~MockReceiver() {} void IncomingPacket(const uint8_t* data, size_t length) { DeliverPacket(data, length); delete [] data; } MOCK_METHOD2(DeliverPacket, DeliveryStatus(const uint8_t*, size_t)); }; class FakeNetworkPipeTest : public ::testing::Test { protected: virtual void SetUp() { TickTime::UseFakeClock(12345); receiver_.reset(new MockReceiver()); } virtual void TearDown() { } void SendPackets(FakeNetworkPipe* pipe, int number_packets, int kPacketSize) { scoped_ptr packet(new uint8_t[kPacketSize]); for (int i = 0; i < number_packets; ++i) { pipe->SendPacket(packet.get(), kPacketSize); } } int PacketTimeMs(int capacity_kbps, int kPacketSize) const { return 8 * kPacketSize / capacity_kbps; } scoped_ptr receiver_; }; void DeleteMemory(uint8_t* data, int length) { delete [] data; } // Test the capacity link and verify we get as many packets as we expect. TEST_F(FakeNetworkPipeTest, CapacityTest) { FakeNetworkPipe::Config config; config.queue_length = 20; config.link_capacity_kbps = 80; scoped_ptr pipe(new FakeNetworkPipe(config)); pipe->SetReceiver(receiver_.get()); // Add 10 packets of 1000 bytes, = 80 kb, and verify it takes one second to // get through the pipe. const int kNumPackets = 10; const int kPacketSize = 1000; SendPackets(pipe.get(), kNumPackets , kPacketSize); // Time to get one packet through the link. const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Time haven't increased yet, so we souldn't get any packets. EXPECT_CALL(*receiver_, DeliverPacket(_, _)) .Times(0); pipe->Process(); // Advance enough time to release one packet. TickTime::AdvanceFakeClock(kPacketTimeMs); EXPECT_CALL(*receiver_, DeliverPacket(_, _)) .Times(1); pipe->Process(); // Release all but one packet TickTime::AdvanceFakeClock(9 * kPacketTimeMs - 1); EXPECT_CALL(*receiver_, DeliverPacket(_, _)) .Times(8); pipe->Process(); // And the last one. TickTime::AdvanceFakeClock(1); EXPECT_CALL(*receiver_, DeliverPacket(_, _)) .Times(1); pipe->Process(); } // Test the extra network delay. TEST_F(FakeNetworkPipeTest, ExtraDelayTest) { FakeNetworkPipe::Config config; config.queue_length = 20; config.queue_delay_ms = 100; config.link_capacity_kbps = 80; scoped_ptr pipe(new FakeNetworkPipe(config)); pipe->SetReceiver(receiver_.get()); const int kNumPackets = 2; const int kPacketSize = 1000; SendPackets(pipe.get(), kNumPackets , kPacketSize); // Time to get one packet through the link. const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Increase more than kPacketTimeMs, but not more than the extra delay. TickTime::AdvanceFakeClock(kPacketTimeMs); EXPECT_CALL(*receiver_, DeliverPacket(_, _)) .Times(0); pipe->Process(); // Advance the network delay to get the first packet. TickTime::AdvanceFakeClock(config.queue_delay_ms); EXPECT_CALL(*receiver_, DeliverPacket(_, _)) .Times(1); pipe->Process(); // Advance one more kPacketTimeMs to get the last packet. TickTime::AdvanceFakeClock(kPacketTimeMs); EXPECT_CALL(*receiver_, DeliverPacket(_, _)) .Times(1); pipe->Process(); } // Test the number of buffers and packets are dropped when sending too many // packets too quickly. TEST_F(FakeNetworkPipeTest, QueueLengthTest) { FakeNetworkPipe::Config config; config.queue_length = 2; config.link_capacity_kbps = 80; scoped_ptr pipe(new FakeNetworkPipe(config)); pipe->SetReceiver(receiver_.get()); const int kPacketSize = 1000; const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Send three packets and verify only 2 are delivered. SendPackets(pipe.get(), 3, kPacketSize); // Increase time enough to deliver all three packets, verify only two are // delivered. TickTime::AdvanceFakeClock(3 * kPacketTimeMs); EXPECT_CALL(*receiver_, DeliverPacket(_, _)) .Times(2); pipe->Process(); } // Test we get statistics as expected. TEST_F(FakeNetworkPipeTest, StatisticsTest) { FakeNetworkPipe::Config config; config.queue_length = 2; config.queue_delay_ms = 20; config.link_capacity_kbps = 80; scoped_ptr pipe(new FakeNetworkPipe(config)); pipe->SetReceiver(receiver_.get()); const int kPacketSize = 1000; const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Send three packets and verify only 2 are delivered. SendPackets(pipe.get(), 3, kPacketSize); TickTime::AdvanceFakeClock(3 * kPacketTimeMs + config.queue_delay_ms); EXPECT_CALL(*receiver_, DeliverPacket(_, _)) .Times(2); pipe->Process(); // Packet 1: kPacketTimeMs + config.queue_delay_ms, // packet 2: 2 * kPacketTimeMs + config.queue_delay_ms => 170 ms average. EXPECT_EQ(pipe->AverageDelay(), 170); EXPECT_EQ(pipe->sent_packets(), 2u); EXPECT_EQ(pipe->dropped_packets(), 1u); EXPECT_EQ(pipe->PercentageLoss(), 1/3.f); } // Change the link capacity half-way through the test and verify that the // delivery times change accordingly. TEST_F(FakeNetworkPipeTest, ChangingCapacityWithEmptyPipeTest) { FakeNetworkPipe::Config config; config.queue_length = 20; config.link_capacity_kbps = 80; scoped_ptr pipe(new FakeNetworkPipe(config)); pipe->SetReceiver(receiver_.get()); // Add 10 packets of 1000 bytes, = 80 kb, and verify it takes one second to // get through the pipe. const int kNumPackets = 10; const int kPacketSize = 1000; SendPackets(pipe.get(), kNumPackets, kPacketSize); // Time to get one packet through the link. int packet_time_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Time hasn't increased yet, so we souldn't get any packets. EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(0); pipe->Process(); // Advance time in steps to release one packet at a time. for (int i = 0; i < kNumPackets; ++i) { TickTime::AdvanceFakeClock(packet_time_ms); EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(1); pipe->Process(); } // Change the capacity. config.link_capacity_kbps /= 2; // Reduce to 50%. pipe->SetConfig(config); // Add another 10 packets of 1000 bytes, = 80 kb, and verify it takes two // seconds to get them through the pipe. SendPackets(pipe.get(), kNumPackets, kPacketSize); // Time to get one packet through the link. packet_time_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Time hasn't increased yet, so we souldn't get any packets. EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(0); pipe->Process(); // Advance time in steps to release one packet at a time. for (int i = 0; i < kNumPackets; ++i) { TickTime::AdvanceFakeClock(packet_time_ms); EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(1); pipe->Process(); } // Check that all the packets were sent. EXPECT_EQ(static_cast(2 * kNumPackets), pipe->sent_packets()); TickTime::AdvanceFakeClock(pipe->TimeUntilNextProcess()); EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(0); pipe->Process(); } // Change the link capacity half-way through the test and verify that the // delivery times change accordingly. TEST_F(FakeNetworkPipeTest, ChangingCapacityWithPacketsInPipeTest) { FakeNetworkPipe::Config config; config.queue_length = 20; config.link_capacity_kbps = 80; scoped_ptr pipe(new FakeNetworkPipe(config)); pipe->SetReceiver(receiver_.get()); // Add 10 packets of 1000 bytes, = 80 kb. const int kNumPackets = 10; const int kPacketSize = 1000; SendPackets(pipe.get(), kNumPackets, kPacketSize); // Time to get one packet through the link at the initial speed. int packet_time_1_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Change the capacity. config.link_capacity_kbps *= 2; // Double the capacity. pipe->SetConfig(config); // Add another 10 packets of 1000 bytes, = 80 kb, and verify it takes two // seconds to get them through the pipe. SendPackets(pipe.get(), kNumPackets, kPacketSize); // Time to get one packet through the link at the new capacity. int packet_time_2_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize); // Time hasn't increased yet, so we souldn't get any packets. EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(0); pipe->Process(); // Advance time in steps to release one packet at a time. for (int i = 0; i < kNumPackets; ++i) { TickTime::AdvanceFakeClock(packet_time_1_ms); EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(1); pipe->Process(); } // Advance time in steps to release one packet at a time. for (int i = 0; i < kNumPackets; ++i) { TickTime::AdvanceFakeClock(packet_time_2_ms); EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(1); pipe->Process(); } // Check that all the packets were sent. EXPECT_EQ(static_cast(2 * kNumPackets), pipe->sent_packets()); TickTime::AdvanceFakeClock(pipe->TimeUntilNextProcess()); EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(0); pipe->Process(); } } // namespace webrtc