Add SetConfig method to FakeNetworkPipe and to DirectTransport

This method allow the user to change the network configuration
during run-time. This is useful when testing how components react
to changing bandwidth.

BUG=2636
R=mflodman@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/9049004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5612 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrik.lundin@webrtc.org 2014-02-26 13:34:52 +00:00
parent eaadecaf98
commit c0e9aebe8f
5 changed files with 125 additions and 1 deletions

View File

@ -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());

View File

@ -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);

View File

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

View File

@ -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);

View File

@ -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<FakeNetworkPipe> 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<size_t>(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<FakeNetworkPipe> 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<size_t>(2 * kNumPackets), pipe->sent_packets());
TickTime::AdvanceFakeClock(pipe->TimeUntilNextProcess());
EXPECT_CALL(*receiver_, DeliverPacket(_, _)).Times(0);
pipe->Process();
}
} // namespace webrtc