diff --git a/webrtc/test/direct_transport.cc b/webrtc/test/direct_transport.cc index 96852ed9c0..fd59815fde 100644 --- a/webrtc/test/direct_transport.cc +++ b/webrtc/test/direct_transport.cc @@ -42,6 +42,10 @@ DirectTransport::DirectTransport( DirectTransport::~DirectTransport() { StopSending(); } +void DirectTransport::SetConfig(const FakeNetworkPipe::Config& config) { + fake_network_.SetConfig(config); +} + void DirectTransport::StopSending() { { CriticalSectionScoped crit_(lock_.get()); diff --git a/webrtc/test/direct_transport.h b/webrtc/test/direct_transport.h index 660ffecc2e..9dc9e1fc00 100644 --- a/webrtc/test/direct_transport.h +++ b/webrtc/test/direct_transport.h @@ -34,6 +34,8 @@ class DirectTransport : public newapi::Transport { explicit DirectTransport(const FakeNetworkPipe::Config& config); ~DirectTransport(); + void SetConfig(const FakeNetworkPipe::Config& config); + virtual void StopSending(); virtual void SetReceiver(PacketReceiver* receiver); diff --git a/webrtc/test/fake_network_pipe.cc b/webrtc/test/fake_network_pipe.cc index 5a2424e75c..c5caef2e80 100644 --- a/webrtc/test/fake_network_pipe.cc +++ b/webrtc/test/fake_network_pipe.cc @@ -93,6 +93,11 @@ void FakeNetworkPipe::SetReceiver(PacketReceiver* receiver) { packet_receiver_ = receiver; } +void FakeNetworkPipe::SetConfig(const FakeNetworkPipe::Config& config) { + CriticalSectionScoped crit(lock_.get()); + config_ = config; // Shallow copy of the struct. +} + void FakeNetworkPipe::SendPacket(const uint8_t* data, size_t data_length) { // A NULL packet_receiver_ means that this pipe will terminate the flow of // packets. diff --git a/webrtc/test/fake_network_pipe.h b/webrtc/test/fake_network_pipe.h index e75045701d..3dcda2982a 100644 --- a/webrtc/test/fake_network_pipe.h +++ b/webrtc/test/fake_network_pipe.h @@ -57,6 +57,9 @@ class FakeNetworkPipe { // Must not be called in parallel with SendPacket or Process. void SetReceiver(PacketReceiver* receiver); + // Sets a new configuration. This won't affect packets already in the pipe. + void SetConfig(const FakeNetworkPipe::Config& config); + // Sends a new packet to the link. void SendPacket(const uint8_t* packet, size_t packet_length); diff --git a/webrtc/test/fake_network_pipe_unittest.cc b/webrtc/test/fake_network_pipe_unittest.cc index 1245f618f1..5076bc0ac6 100644 --- a/webrtc/test/fake_network_pipe_unittest.cc +++ b/webrtc/test/fake_network_pipe_unittest.cc @@ -53,7 +53,7 @@ class FakeNetworkPipeTest : public ::testing::Test { } } - int PacketTimeMs(int capacity_kbps, int kPacketSize) { + int PacketTimeMs(int capacity_kbps, int kPacketSize) const { return 8 * kPacketSize / capacity_kbps; } @@ -193,4 +193,114 @@ TEST_F(FakeNetworkPipeTest, StatisticsTest) { 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