
These tests are not included in bots, this will be fixed in a follow-up by pbos@webrtc.org. R=pbos@webrtc.org Review URL: https://webrtc-codereview.appspot.com/13109004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6837 4adac7df-926f-26a2-2b94-8c16560cd09d
309 lines
10 KiB
C++
309 lines
10 KiB
C++
/*
|
|
* 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());
|
|
ON_CALL(*receiver_, DeliverPacket(_, _))
|
|
.WillByDefault(Return(PacketReceiver::DELIVERY_OK));
|
|
}
|
|
|
|
virtual void TearDown() {
|
|
}
|
|
|
|
void SendPackets(FakeNetworkPipe* pipe, int number_packets, int kPacketSize) {
|
|
scoped_ptr<uint8_t[]> 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<MockReceiver> 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_packets = 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.
|
|
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_packets = 20;
|
|
config.queue_delay_ms = 100;
|
|
config.link_capacity_kbps = 80;
|
|
scoped_ptr<FakeNetworkPipe> 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_packets = 2;
|
|
config.link_capacity_kbps = 80;
|
|
scoped_ptr<FakeNetworkPipe> 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_packets = 2;
|
|
config.queue_delay_ms = 20;
|
|
config.link_capacity_kbps = 80;
|
|
scoped_ptr<FakeNetworkPipe> 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_packets = 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_packets = 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
|