webrtc/modules/congestion_controller/goog_cc/probe_controller_unittest.cc
Per K b812b7a86b Delay probes after route change until transport is writable
Ensure probes are not created until after the transport becomes writable even if the network route change.
DTLS negotiation must complete before there is a point in sending probes.

Bug: webrtc:14928
Change-Id: Ib3cb93aef9f38e306b094dd700ed595cf9eb3f32
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/301362
Reviewed-by: Diep Bui <diepbp@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39870}
2023-04-17 10:18:34 +00:00

1189 lines
50 KiB
C++

/*
* 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/probe_controller.h"
#include <memory>
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/clock.h"
#include "test/explicit_key_value_config.h"
#include "test/gmock.h"
#include "test/gtest.h"
using ::testing::IsEmpty;
using ::testing::NiceMock;
namespace webrtc {
namespace test {
namespace {
constexpr DataRate kMinBitrate = DataRate::BitsPerSec(100);
constexpr DataRate kStartBitrate = DataRate::BitsPerSec(300);
constexpr DataRate kMaxBitrate = DataRate::BitsPerSec(10000);
constexpr TimeDelta kExponentialProbingTimeout = TimeDelta::Seconds(5);
constexpr TimeDelta kAlrProbeInterval = TimeDelta::Seconds(5);
constexpr TimeDelta kAlrEndedTimeout = TimeDelta::Seconds(3);
constexpr TimeDelta kBitrateDropTimeout = TimeDelta::Seconds(5);
} // namespace
class ProbeControllerFixture {
public:
explicit ProbeControllerFixture(absl::string_view field_trials = "")
: field_trial_config_(field_trials), clock_(100000000L) {}
std::unique_ptr<ProbeController> CreateController() {
return std::make_unique<ProbeController>(&field_trial_config_,
&mock_rtc_event_log);
}
Timestamp CurrentTime() { return clock_.CurrentTime(); }
void AdvanceTime(TimeDelta delta) { clock_.AdvanceTime(delta); }
ExplicitKeyValueConfig field_trial_config_;
SimulatedClock clock_;
NiceMock<MockRtcEventLog> mock_rtc_event_log;
};
TEST(ProbeControllerTest, InitiatesProbingAtStart) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_GE(probes.size(), 2u);
}
TEST(ProbeControllerTest, SetsDefaultTargetDurationAndTargetProbeCount) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
std::vector<ProbeClusterConfig> probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_GE(probes.size(), 2u);
EXPECT_EQ(probes[0].target_duration, TimeDelta::Millis(15));
EXPECT_EQ(probes[0].target_probe_count, 5);
}
TEST(ProbeControllerTest,
FieldTrialsOverrideDefaultTargetDurationAndTargetProbeCount) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingBehavior/"
"min_probe_packets_sent:2,min_probe_duration:123ms/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
std::vector<ProbeClusterConfig> probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_GE(probes.size(), 2u);
EXPECT_EQ(probes[0].target_duration, TimeDelta::Millis(123));
EXPECT_EQ(probes[0].target_probe_count, 2);
}
TEST(ProbeControllerTest, ProbeOnlyWhenNetworkIsUp) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->OnNetworkAvailability(
{.at_time = fixture.CurrentTime(), .network_available = false});
probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
kMaxBitrate, fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probes = probe_controller->OnNetworkAvailability(
{.at_time = fixture.CurrentTime(), .network_available = true});
EXPECT_GE(probes.size(), 2u);
}
TEST(ProbeControllerTest, CanConfigureInitialProbeRateFactor) {
ProbeControllerFixture fixture("WebRTC-Bwe-ProbingConfiguration/p1:2,p2:3/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate * 2);
EXPECT_EQ(probes[1].target_data_rate, kStartBitrate * 3);
}
TEST(ProbeControllerTest, DisableSecondInitialProbeIfRateFactorZero) {
ProbeControllerFixture fixture("WebRTC-Bwe-ProbingConfiguration/p1:2,p2:0/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate * 2);
}
TEST(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
// Long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate + DataRate::BitsPerSec(100),
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrate.bps() + 100);
}
TEST(ProbeControllerTest, ProbesOnMaxAllocatedBitrateIncreaseOnlyWhenInAlr) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate - DataRate::BitsPerSec(1),
BandwidthLimitedCause::kDelayBasedLimited, fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
// Probe when in alr.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
probes = probe_controller->OnMaxTotalAllocatedBitrate(
kMaxBitrate + DataRate::BitsPerSec(1), fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
EXPECT_EQ(probes.at(0).target_data_rate, kMaxBitrate);
// Do not probe when not in alr.
probe_controller->SetAlrStartTimeMs(absl::nullopt);
probes = probe_controller->OnMaxTotalAllocatedBitrate(
kMaxBitrate + DataRate::BitsPerSec(2), fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, CanDisableProbingOnMaxTotalAllocatedBitrateIncrease) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"probe_max_allocation:false/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate - DataRate::BitsPerSec(1),
BandwidthLimitedCause::kDelayBasedLimited, fixture.CurrentTime());
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
// Do no probe, since probe_max_allocation:false.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
probes = probe_controller->OnMaxTotalAllocatedBitrate(
kMaxBitrate + DataRate::BitsPerSec(1), fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncreaseAtMaxBitrate) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
// Long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate + DataRate::BitsPerSec(100),
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate,
kMaxBitrate + DataRate::BitsPerSec(100));
}
TEST(ProbeControllerTest, TestExponentialProbing) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
// Repeated probe should only be sent when estimated bitrate climbs above
// 0.7 * 6 * kStartBitrate = 1260.
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1000), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1800), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 2 * 1800);
}
TEST(ProbeControllerTest, TestExponentialProbingTimeout) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
// Advance far enough to cause a time out in waiting for probing result.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1800), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, RequestProbeInAlr) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_GE(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
}
TEST(ProbeControllerTest, RequestProbeWhenAlrEndedRecently) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(absl::nullopt);
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrEndedTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrEndedTimeout - TimeDelta::Millis(1));
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
}
TEST(ProbeControllerTest, RequestProbeWhenAlrNotEndedRecently) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(absl::nullopt);
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrEndedTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrEndedTimeout + TimeDelta::Millis(1));
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, RequestProbeWhenBweDropNotRecent) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
fixture.AdvanceTime(kBitrateDropTimeout + TimeDelta::Millis(1));
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, PeriodicProbing) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
Timestamp start_time = fixture.CurrentTime();
// Expect the controller to send a new probe after 5s has passed.
probe_controller->SetAlrStartTimeMs(start_time.ms());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 1000);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// The following probe should be sent at 10s into ALR.
probe_controller->SetAlrStartTimeMs(start_time.ms());
fixture.AdvanceTime(TimeDelta::Seconds(4));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probe_controller->SetAlrStartTimeMs(start_time.ms());
fixture.AdvanceTime(TimeDelta::Seconds(1));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, PeriodicProbingAfterReset) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
Timestamp alr_start_time = fixture.CurrentTime();
probe_controller->SetAlrStartTimeMs(alr_start_time.ms());
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->Reset(fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(10));
probes = probe_controller->Process(fixture.CurrentTime());
// Since bitrates are not yet set, no probe is sent event though we are in ALR
// mode.
EXPECT_TRUE(probes.empty());
probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
// Make sure we use `kStartBitrateBps` as the estimated bitrate
// until SetEstimatedBitrate is called with an updated estimate.
fixture.AdvanceTime(TimeDelta::Seconds(10));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate * 2);
}
TEST(ProbeControllerTest, NoProbesWhenTransportIsNotWritable) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
probe_controller->EnablePeriodicAlrProbing(true);
std::vector<ProbeClusterConfig> probes =
probe_controller->OnNetworkAvailability({.network_available = false});
EXPECT_THAT(probes, IsEmpty());
EXPECT_THAT(probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
kMaxBitrate, fixture.CurrentTime()),
IsEmpty());
fixture.AdvanceTime(TimeDelta::Seconds(10));
EXPECT_THAT(probe_controller->Process(fixture.CurrentTime()), IsEmpty());
// Controller is reset after a network route change.
// But, a probe should not be sent since the transport is not writable.
// Transport is not writable until after DTLS negotiation completes.
// However, the bitrate constraints may change.
probe_controller->Reset(fixture.CurrentTime());
EXPECT_THAT(
probe_controller->SetBitrates(2 * kMinBitrate, 2 * kStartBitrate,
2 * kMaxBitrate, fixture.CurrentTime()),
IsEmpty());
fixture.AdvanceTime(TimeDelta::Seconds(10));
EXPECT_THAT(probe_controller->Process(fixture.CurrentTime()), IsEmpty());
}
TEST(ProbeControllerTest, TestExponentialProbingOverflow) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const DataRate kMbpsMultiplier = DataRate::KilobitsPerSec(1000);
auto probes = probe_controller->SetBitrates(kMinBitrate, 10 * kMbpsMultiplier,
100 * kMbpsMultiplier,
fixture.CurrentTime());
// Verify that probe bitrate is capped at the specified max bitrate.
probes = probe_controller->SetEstimatedBitrate(
60 * kMbpsMultiplier, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, 100 * kMbpsMultiplier);
// Verify that repeated probes aren't sent.
probes = probe_controller->SetEstimatedBitrate(
100 * kMbpsMultiplier, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, TestAllocatedBitrateCap) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const DataRate kMbpsMultiplier = DataRate::KilobitsPerSec(1000);
const DataRate kMaxBitrate = 100 * kMbpsMultiplier;
auto probes = probe_controller->SetBitrates(
kMinBitrate, 10 * kMbpsMultiplier, kMaxBitrate, fixture.CurrentTime());
// Configure ALR for periodic probing.
probe_controller->EnablePeriodicAlrProbing(true);
Timestamp alr_start_time = fixture.CurrentTime();
probe_controller->SetAlrStartTimeMs(alr_start_time.ms());
DataRate estimated_bitrate = kMaxBitrate / 10;
probes = probe_controller->SetEstimatedBitrate(
estimated_bitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Set a max allocated bitrate below the current estimate.
DataRate max_allocated = estimated_bitrate - 1 * kMbpsMultiplier;
probes = probe_controller->OnMaxTotalAllocatedBitrate(max_allocated,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty()); // No probe since lower than current max.
// Probes such as ALR capped at 2x the max allocation limit.
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, 2 * max_allocated);
// Remove allocation limit.
EXPECT_TRUE(
probe_controller
->OnMaxTotalAllocatedBitrate(DataRate::Zero(), fixture.CurrentTime())
.empty());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, estimated_bitrate * 2);
}
TEST(ProbeControllerTest, ConfigurableProbingFieldTrial) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"p1:2,p2:5,step_size:3,further_probe_threshold:0.8,"
"alloc_p1:2,alloc_p2,min_probe_packets_sent:2/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
DataRate::KilobitsPerSec(5000),
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 600);
EXPECT_EQ(probes[0].target_probe_count, 2);
EXPECT_EQ(probes[1].target_data_rate.bps(), 1500);
EXPECT_EQ(probes[1].target_probe_count, 2);
// Repeated probe should only be sent when estimated bitrate climbs above
// 0.8 * 5 * kStartBitrateBps = 1200.
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1100), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 3 * 1250);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
probes = probe_controller->OnMaxTotalAllocatedBitrate(
DataRate::KilobitsPerSec(200), fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 400'000);
}
TEST(ProbeControllerTest, LimitAlrProbeWhenLossBasedBweLimited) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
BandwidthLimitedCause::kLossLimitedBweIncreasing, fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(6));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, 1.5 * DataRate::BitsPerSec(500));
probes = probe_controller->SetEstimatedBitrate(
1.5 * DataRate::BitsPerSec(500),
BandwidthLimitedCause::kDelayBasedLimited, fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(6));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
EXPECT_GT(probes[0].target_data_rate, 1.5 * 1.5 * DataRate::BitsPerSec(500));
}
TEST(ProbeControllerTest, PeriodicProbeAtUpperNetworkStateEstimate) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/network_state_interval:5s/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(5000), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = DataRate::KilobitsPerSec(6);
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
}
TEST(ProbeControllerTest,
LimitProbeAtUpperNetworkStateEstimateIfLossBasedLimited) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = DataRate::BitsPerSec(700);
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
BandwidthLimitedCause::kLossLimitedBweIncreasing, fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
EXPECT_EQ(probes[0].target_data_rate, DataRate::BitsPerSec(700));
}
TEST(ProbeControllerTest, AlrProbesLimitedByNetworkStateEstimate) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/network_state_interval:5s/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::KilobitsPerSec(6), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, kMaxBitrate);
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = DataRate::BitsPerSec(8000);
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
}
TEST(ProbeControllerTest, CanSetLongerProbeDurationAfterNetworkStateEstimate) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,network_state_probe_duration:100ms/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::KilobitsPerSec(5), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
EXPECT_LT(probes[0].target_duration, TimeDelta::Millis(100));
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = DataRate::KilobitsPerSec(6);
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_duration, TimeDelta::Millis(100));
}
TEST(ProbeControllerTest, ProbeInAlrIfLossBasedIncreasing) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->EnablePeriodicAlrProbing(true);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweIncreasing,
fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
// Probe when in alr.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes.at(0).target_data_rate, 1.5 * kStartBitrate);
}
TEST(ProbeControllerTest, ProbeFurtherInAlrIfLossBasedIncreasing) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->EnablePeriodicAlrProbing(true);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweIncreasing,
fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
// Probe when in alr.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
ASSERT_EQ(probes.at(0).target_data_rate, 1.5 * kStartBitrate);
probes = probe_controller->SetEstimatedBitrate(
1.5 * kStartBitrate, BandwidthLimitedCause::kLossLimitedBweIncreasing,
fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, 1.5 * 1.5 * kStartBitrate);
}
TEST(ProbeControllerTest, NotProbeWhenInAlrIfLossBasedDecreases) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->EnablePeriodicAlrProbing(true);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweDecreasing,
fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
// Not probe in alr when loss based estimate decreases.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, NotProbeIfLossBasedIncreasingOutsideAlr) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->EnablePeriodicAlrProbing(true);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweIncreasing,
fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
probe_controller->SetAlrStartTimeMs(absl::nullopt);
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, ProbeFurtherWhenLossBasedIsSameAsDelayBasedEstimate) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = 5 * kStartBitrate;
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
DataRate probe_target_rate = probes[0].target_data_rate;
EXPECT_LT(probe_target_rate, state_estimate.link_capacity_upper);
// Expect that more probes are sent if BWE is the same as delay based
// estimate.
probes = probe_controller->SetEstimatedBitrate(
probe_target_rate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
EXPECT_EQ(probes[0].target_data_rate, 2 * probe_target_rate);
}
TEST(ProbeControllerTest, ProbeIfEstimateLowerThanNetworkStateEstimate) {
// Periodic probe every 1 second if estimate is lower than 50% of the
// NetworkStateEstimate.
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/est_lower_than_network_interval:1s,"
"est_lower_than_network_ratio:0.5,limit_probe_"
"target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = kStartBitrate;
probe_controller->SetNetworkStateEstimate(state_estimate);
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
state_estimate.link_capacity_upper = kStartBitrate * 3;
probe_controller->SetNetworkStateEstimate(state_estimate);
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_GT(probes[0].target_data_rate, kStartBitrate);
// If network state not increased, send another probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
// Stop probing if estimate increase. We might probe further here though.
probes = probe_controller->SetEstimatedBitrate(
2 * kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// No more periodic probes.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, DontProbeFurtherWhenLossLimited) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = 3 * kStartBitrate;
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
EXPECT_LT(probes[0].target_data_rate, state_estimate.link_capacity_upper);
// Expect that no more probes are sent immediately if BWE is loss limited.
probes = probe_controller->SetEstimatedBitrate(
probes[0].target_data_rate,
BandwidthLimitedCause::kLossLimitedBweDecreasing, fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, ProbeFurtherWhenDelayBasedLimited) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = 3 * kStartBitrate;
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
EXPECT_LT(probes[0].target_data_rate, state_estimate.link_capacity_upper);
// Since the probe was successfull, expect to continue probing.
probes = probe_controller->SetEstimatedBitrate(
probes[0].target_data_rate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
}
TEST(ProbeControllerTest,
ProbeFurtherIfNetworkStateEstimateIncreaseAfterProbeSent) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = 1.2 * probes[0].target_data_rate / 2;
probe_controller->SetNetworkStateEstimate(state_estimate);
// No immediate further probing since probe result is low.
probes = probe_controller->SetEstimatedBitrate(
probes[0].target_data_rate / 2, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
EXPECT_LE(probes[0].target_data_rate, state_estimate.link_capacity_upper);
// If the network state estimate increase above the threshold to probe
// further, and the probe suceeed, expect a new probe.
state_estimate.link_capacity_upper = 3 * kStartBitrate;
probe_controller->SetNetworkStateEstimate(state_estimate);
probes = probe_controller->SetEstimatedBitrate(
probes[0].target_data_rate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
// But no more probes if estimate is close to the link capacity.
probes = probe_controller->SetEstimatedBitrate(
state_estimate.link_capacity_upper * 0.9,
BandwidthLimitedCause::kDelayBasedLimited, fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, SkipAlrProbeIfEstimateLargerThanMaxProbe) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"skip_if_est_larger_than_fraction_of_max:0.9/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(TimeDelta::Seconds(10));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
// But if the max rate increase, A new probe is sent.
probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, 2 * kMaxBitrate, fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
}
TEST(ProbeControllerTest,
SkipAlrProbeIfEstimateLargerThanFractionOfMaxAllocated) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"skip_if_est_larger_than_fraction_of_max:1.0/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate / 2, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(10));
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
probes = probe_controller->OnMaxTotalAllocatedBitrate(kMaxBitrate / 2,
fixture.CurrentTime());
// No probes since total allocated is not higher than the current estimate.
EXPECT_TRUE(probes.empty());
fixture.AdvanceTime(TimeDelta::Seconds(2));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
// But if the max allocated increase, A new probe is sent.
probes = probe_controller->OnMaxTotalAllocatedBitrate(
kMaxBitrate / 2 + DataRate::BitsPerSec(1), fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
}
TEST(ProbeControllerTest, SkipNetworkStateProbeIfEstimateLargerThanMaxProbe) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:2s,skip_if_est_larger_than_fraction_of_max:0.9/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
probe_controller->SetNetworkStateEstimate(
{.link_capacity_upper = 2 * kMaxBitrate});
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
fixture.AdvanceTime(TimeDelta::Seconds(10));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, SendsProbeIfNetworkStateEstimateLowerThanMaxProbe) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:2s,skip_if_est_larger_than_fraction_of_max:0.9,"
"/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
probe_controller->SetNetworkStateEstimate(
{.link_capacity_upper = 2 * kMaxBitrate});
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
// Need to wait at least two seconds before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(2100));
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probe_controller->SetNetworkStateEstimate(
{.link_capacity_upper = 2 * kStartBitrate});
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
}
TEST(ProbeControllerTest, DontSendProbeIfNetworkStateEstimateIsZero) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetNetworkStateEstimate(
{.link_capacity_upper = kStartBitrate});
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
probe_controller->SetNetworkStateEstimate(
{.link_capacity_upper = DataRate::Zero()});
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
fixture.AdvanceTime(TimeDelta::Seconds(6));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, DontProbeIfDelayIncreased) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,not_probe_if_delay_increased:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = 3 * kStartBitrate;
probe_controller->SetNetworkStateEstimate(state_estimate);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimitedDelayIncreased,
fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, DontProbeIfHighRtt) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,not_probe_if_delay_increased:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = 3 * kStartBitrate;
probe_controller->SetNetworkStateEstimate(state_estimate);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kRttBasedBackOffHighRtt,
fixture.CurrentTime());
ASSERT_TRUE(probes.empty());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
} // namespace test
} // namespace webrtc