Source code
Revision control
Copy as Markdown
Other Tools
/*
* Copyright (c) 2016 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 "modules/congestion_controller/goog_cc/trendline_estimator.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <vector>
#include "api/transport/bandwidth_usage.h"
#include "api/transport/field_trial_based_config.h"
#include "rtc_base/checks.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
class PacketTimeGenerator {
public:
PacketTimeGenerator(int64_t initial_clock, double time_between_packets)
: initial_clock_(initial_clock),
time_between_packets_(time_between_packets),
packets_(0) {}
int64_t operator()() {
return initial_clock_ + time_between_packets_ * packets_++;
}
private:
const int64_t initial_clock_;
const double time_between_packets_;
size_t packets_;
};
class TrendlineEstimatorTest : public testing::Test {
public:
TrendlineEstimatorTest()
: send_times(kPacketCount),
recv_times(kPacketCount),
packet_sizes(kPacketCount),
config(),
estimator(&config, nullptr),
count(1) {
std::fill(packet_sizes.begin(), packet_sizes.end(), kPacketSizeBytes);
}
void RunTestUntilStateChange() {
RTC_DCHECK_EQ(send_times.size(), kPacketCount);
RTC_DCHECK_EQ(recv_times.size(), kPacketCount);
RTC_DCHECK_EQ(packet_sizes.size(), kPacketCount);
RTC_DCHECK_GE(count, 1);
RTC_DCHECK_LT(count, kPacketCount);
auto initial_state = estimator.State();
for (; count < kPacketCount; count++) {
double recv_delta = recv_times[count] - recv_times[count - 1];
double send_delta = send_times[count] - send_times[count - 1];
estimator.Update(recv_delta, send_delta, send_times[count],
recv_times[count], packet_sizes[count], true);
if (estimator.State() != initial_state) {
return;
}
}
}
protected:
const size_t kPacketCount = 25;
const size_t kPacketSizeBytes = 1200;
std::vector<int64_t> send_times;
std::vector<int64_t> recv_times;
std::vector<size_t> packet_sizes;
const FieldTrialBasedConfig config;
TrendlineEstimator estimator;
size_t count;
};
} // namespace
TEST_F(TrendlineEstimatorTest, Normal) {
PacketTimeGenerator send_time_generator(123456789 /*initial clock*/,
20 /*20 ms between sent packets*/);
std::generate(send_times.begin(), send_times.end(), send_time_generator);
PacketTimeGenerator recv_time_generator(987654321 /*initial clock*/,
20 /*delivered at the same pace*/);
std::generate(recv_times.begin(), recv_times.end(), recv_time_generator);
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwNormal);
RunTestUntilStateChange();
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwNormal);
EXPECT_EQ(count, kPacketCount); // All packets processed
}
TEST_F(TrendlineEstimatorTest, Overusing) {
PacketTimeGenerator send_time_generator(123456789 /*initial clock*/,
20 /*20 ms between sent packets*/);
std::generate(send_times.begin(), send_times.end(), send_time_generator);
PacketTimeGenerator recv_time_generator(987654321 /*initial clock*/,
1.1 * 20 /*10% slower delivery*/);
std::generate(recv_times.begin(), recv_times.end(), recv_time_generator);
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwNormal);
RunTestUntilStateChange();
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwOverusing);
RunTestUntilStateChange();
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwOverusing);
EXPECT_EQ(count, kPacketCount); // All packets processed
}
TEST_F(TrendlineEstimatorTest, Underusing) {
PacketTimeGenerator send_time_generator(123456789 /*initial clock*/,
20 /*20 ms between sent packets*/);
std::generate(send_times.begin(), send_times.end(), send_time_generator);
PacketTimeGenerator recv_time_generator(987654321 /*initial clock*/,
0.85 * 20 /*15% faster delivery*/);
std::generate(recv_times.begin(), recv_times.end(), recv_time_generator);
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwNormal);
RunTestUntilStateChange();
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwUnderusing);
RunTestUntilStateChange();
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwUnderusing);
EXPECT_EQ(count, kPacketCount); // All packets processed
}
TEST_F(TrendlineEstimatorTest, IncludesSmallPacketsByDefault) {
PacketTimeGenerator send_time_generator(123456789 /*initial clock*/,
20 /*20 ms between sent packets*/);
std::generate(send_times.begin(), send_times.end(), send_time_generator);
PacketTimeGenerator recv_time_generator(987654321 /*initial clock*/,
1.1 * 20 /*10% slower delivery*/);
std::generate(recv_times.begin(), recv_times.end(), recv_time_generator);
std::fill(packet_sizes.begin(), packet_sizes.end(), 100);
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwNormal);
RunTestUntilStateChange();
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwOverusing);
RunTestUntilStateChange();
EXPECT_EQ(estimator.State(), BandwidthUsage::kBwOverusing);
EXPECT_EQ(count, kPacketCount); // All packets processed
}
} // namespace webrtc