tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

bitrate_controller_unittest.cc (14326B)


      1 /*
      2 *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/congestion_controller/pcc/bitrate_controller.h"
     12 
     13 #include <cstddef>
     14 #include <memory>
     15 #include <optional>
     16 #include <utility>
     17 #include <vector>
     18 
     19 #include "api/transport/network_types.h"
     20 #include "api/units/data_rate.h"
     21 #include "api/units/data_size.h"
     22 #include "api/units/time_delta.h"
     23 #include "api/units/timestamp.h"
     24 #include "modules/congestion_controller/pcc/monitor_interval.h"
     25 #include "modules/congestion_controller/pcc/utility_function.h"
     26 #include "test/gmock.h"
     27 #include "test/gtest.h"
     28 
     29 namespace webrtc {
     30 namespace pcc {
     31 namespace test {
     32 namespace {
     33 constexpr double kInitialConversionFactor = 1;
     34 constexpr double kInitialDynamicBoundary = 0.05;
     35 constexpr double kDynamicBoundaryIncrement = 0.1;
     36 
     37 constexpr double kDelayGradientCoefficient = 900;
     38 constexpr double kLossCoefficient = 11.35;
     39 constexpr double kThroughputCoefficient = 500 * 1000;
     40 constexpr double kThroughputPower = 0.99;
     41 constexpr double kDelayGradientThreshold = 0.01;
     42 constexpr double kDelayGradientNegativeBound = 10;
     43 
     44 constexpr DataRate kTargetSendingRate = DataRate::KilobitsPerSec(300);
     45 constexpr double kEpsilon = 0.05;
     46 constexpr Timestamp kStartTime = Timestamp::Micros(0);
     47 constexpr TimeDelta kPacketsDelta = TimeDelta::Millis(1);
     48 constexpr TimeDelta kIntervalDuration = TimeDelta::Millis(1000);
     49 constexpr TimeDelta kDefaultRtt = TimeDelta::Millis(1000);
     50 constexpr DataSize kDefaultDataSize = DataSize::Bytes(100);
     51 
     52 std::vector<PacketResult> CreatePacketResults(
     53    const std::vector<Timestamp>& packets_send_times,
     54    const std::vector<Timestamp>& packets_received_times = {},
     55    const std::vector<DataSize>& packets_sizes = {}) {
     56  std::vector<PacketResult> packet_results;
     57  PacketResult packet_result;
     58  SentPacket sent_packet;
     59  for (size_t i = 0; i < packets_send_times.size(); ++i) {
     60    sent_packet.send_time = packets_send_times[i];
     61    if (packets_sizes.empty()) {
     62      sent_packet.size = kDefaultDataSize;
     63    } else {
     64      sent_packet.size = packets_sizes[i];
     65    }
     66    packet_result.sent_packet = sent_packet;
     67    if (packets_received_times.empty()) {
     68      packet_result.receive_time = packets_send_times[i] + kDefaultRtt;
     69    } else {
     70      packet_result.receive_time = packets_received_times[i];
     71    }
     72    packet_results.push_back(packet_result);
     73  }
     74  return packet_results;
     75 }
     76 
     77 class MockUtilityFunction : public PccUtilityFunctionInterface {
     78 public:
     79  MOCK_METHOD(double,
     80              Compute,
     81              (const PccMonitorInterval& monitor_interval),
     82              (const, override));
     83 };
     84 
     85 }  // namespace
     86 
     87 TEST(PccBitrateControllerTest, IncreaseRateWhenNoChangesForTestBitrates) {
     88  PccBitrateController bitrate_controller(
     89      kInitialConversionFactor, kInitialDynamicBoundary,
     90      kDynamicBoundaryIncrement, kDelayGradientCoefficient, kLossCoefficient,
     91      kThroughputCoefficient, kThroughputPower, kDelayGradientThreshold,
     92      kDelayGradientNegativeBound);
     93  VivaceUtilityFunction utility_function(
     94      kDelayGradientCoefficient, kLossCoefficient, kThroughputCoefficient,
     95      kThroughputPower, kDelayGradientThreshold, kDelayGradientNegativeBound);
     96  std::vector<PccMonitorInterval> monitor_block{
     97      PccMonitorInterval(kTargetSendingRate * (1 + kEpsilon), kStartTime,
     98                         kIntervalDuration),
     99      PccMonitorInterval(kTargetSendingRate * (1 - kEpsilon),
    100                         kStartTime + kIntervalDuration, kIntervalDuration)};
    101  monitor_block[0].OnPacketsFeedback(
    102      CreatePacketResults({kStartTime + kPacketsDelta,
    103                           kStartTime + kIntervalDuration + kPacketsDelta,
    104                           kStartTime + 3 * kIntervalDuration},
    105                          {}, {}));
    106  monitor_block[1].OnPacketsFeedback(
    107      CreatePacketResults({kStartTime + kPacketsDelta,
    108                           kStartTime + kIntervalDuration + kPacketsDelta,
    109                           kStartTime + 3 * kIntervalDuration},
    110                          {}, {}));
    111  // For both of the monitor intervals there were no change in rtt gradient
    112  // and in packet loss. Since the only difference is in the sending rate,
    113  // the higher sending rate should be chosen by congestion controller.
    114  EXPECT_GT(bitrate_controller
    115                .ComputeRateUpdateForOnlineLearningMode(monitor_block,
    116                                                        kTargetSendingRate)
    117                .bps(),
    118            kTargetSendingRate.bps());
    119 }
    120 
    121 TEST(PccBitrateControllerTest, NoChangesWhenUtilityFunctionDoesntChange) {
    122  std::unique_ptr<MockUtilityFunction> mock_utility_function =
    123      std::make_unique<MockUtilityFunction>();
    124  EXPECT_CALL(*mock_utility_function, Compute(::testing::_))
    125      .Times(2)
    126      .WillOnce(::testing::Return(100))
    127      .WillOnce(::testing::Return(100));
    128 
    129  PccBitrateController bitrate_controller(
    130      kInitialConversionFactor, kInitialDynamicBoundary,
    131      kDynamicBoundaryIncrement, std::move(mock_utility_function));
    132  std::vector<PccMonitorInterval> monitor_block{
    133      PccMonitorInterval(kTargetSendingRate * (1 + kEpsilon), kStartTime,
    134                         kIntervalDuration),
    135      PccMonitorInterval(kTargetSendingRate * (1 - kEpsilon),
    136                         kStartTime + kIntervalDuration, kIntervalDuration)};
    137  // To complete collecting feedback within monitor intervals.
    138  monitor_block[0].OnPacketsFeedback(
    139      CreatePacketResults({kStartTime + 3 * kIntervalDuration}, {}, {}));
    140  monitor_block[1].OnPacketsFeedback(
    141      CreatePacketResults({kStartTime + 3 * kIntervalDuration}, {}, {}));
    142  // Because we don't have any packets inside of monitor intervals, utility
    143  // function should be zero for both of them and the sending rate should not
    144  // change.
    145  EXPECT_EQ(bitrate_controller
    146                .ComputeRateUpdateForOnlineLearningMode(monitor_block,
    147                                                        kTargetSendingRate)
    148                .bps(),
    149            kTargetSendingRate.bps());
    150 }
    151 
    152 TEST(PccBitrateControllerTest, NoBoundaryWhenSmallGradient) {
    153  std::unique_ptr<MockUtilityFunction> mock_utility_function =
    154      std::make_unique<MockUtilityFunction>();
    155  constexpr double kFirstMonitorIntervalUtility = 0;
    156  const double kSecondMonitorIntervalUtility =
    157      2 * kTargetSendingRate.bps() * kEpsilon;
    158 
    159  EXPECT_CALL(*mock_utility_function, Compute(::testing::_))
    160      .Times(2)
    161      .WillOnce(::testing::Return(kFirstMonitorIntervalUtility))
    162      .WillOnce(::testing::Return(kSecondMonitorIntervalUtility));
    163 
    164  PccBitrateController bitrate_controller(
    165      kInitialConversionFactor, kInitialDynamicBoundary,
    166      kDynamicBoundaryIncrement, std::move(mock_utility_function));
    167  std::vector<PccMonitorInterval> monitor_block{
    168      PccMonitorInterval(kTargetSendingRate * (1 + kEpsilon), kStartTime,
    169                         kIntervalDuration),
    170      PccMonitorInterval(kTargetSendingRate * (1 - kEpsilon),
    171                         kStartTime + kIntervalDuration, kIntervalDuration)};
    172  // To complete collecting feedback within monitor intervals.
    173  monitor_block[0].OnPacketsFeedback(
    174      CreatePacketResults({kStartTime + 3 * kIntervalDuration}, {}, {}));
    175  monitor_block[1].OnPacketsFeedback(
    176      CreatePacketResults({kStartTime + 3 * kIntervalDuration}, {}, {}));
    177 
    178  double gradient =
    179      (kFirstMonitorIntervalUtility - kSecondMonitorIntervalUtility) /
    180      (kTargetSendingRate.bps() * 2 * kEpsilon);
    181  // When the gradient is small we don't hit the dynamic boundary.
    182  EXPECT_EQ(bitrate_controller
    183                .ComputeRateUpdateForOnlineLearningMode(monitor_block,
    184                                                        kTargetSendingRate)
    185                .bps(),
    186            kTargetSendingRate.bps() + kInitialConversionFactor * gradient);
    187 }
    188 
    189 TEST(PccBitrateControllerTest, FaceBoundaryWhenLargeGradient) {
    190  std::unique_ptr<MockUtilityFunction> mock_utility_function =
    191      std::make_unique<MockUtilityFunction>();
    192  constexpr double kFirstMonitorIntervalUtility = 0;
    193  const double kSecondMonitorIntervalUtility =
    194      10 * kInitialDynamicBoundary * kTargetSendingRate.bps() * 2 *
    195      kTargetSendingRate.bps() * kEpsilon;
    196 
    197  EXPECT_CALL(*mock_utility_function, Compute(::testing::_))
    198      .Times(4)
    199      .WillOnce(::testing::Return(kFirstMonitorIntervalUtility))
    200      .WillOnce(::testing::Return(kSecondMonitorIntervalUtility))
    201      .WillOnce(::testing::Return(kFirstMonitorIntervalUtility))
    202      .WillOnce(::testing::Return(kSecondMonitorIntervalUtility));
    203 
    204  PccBitrateController bitrate_controller(
    205      kInitialConversionFactor, kInitialDynamicBoundary,
    206      kDynamicBoundaryIncrement, std::move(mock_utility_function));
    207  std::vector<PccMonitorInterval> monitor_block{
    208      PccMonitorInterval(kTargetSendingRate * (1 + kEpsilon), kStartTime,
    209                         kIntervalDuration),
    210      PccMonitorInterval(kTargetSendingRate * (1 - kEpsilon),
    211                         kStartTime + kIntervalDuration, kIntervalDuration)};
    212  // To complete collecting feedback within monitor intervals.
    213  monitor_block[0].OnPacketsFeedback(
    214      CreatePacketResults({kStartTime + 3 * kIntervalDuration}, {}, {}));
    215  monitor_block[1].OnPacketsFeedback(
    216      CreatePacketResults({kStartTime + 3 * kIntervalDuration}, {}, {}));
    217  // The utility function gradient is too big and we hit the dynamic boundary.
    218  EXPECT_EQ(bitrate_controller.ComputeRateUpdateForOnlineLearningMode(
    219                monitor_block, kTargetSendingRate),
    220            kTargetSendingRate * (1 - kInitialDynamicBoundary));
    221  // For the second time we hit the dynamic boundary in the same direction, the
    222  // boundary should increase.
    223  EXPECT_EQ(bitrate_controller
    224                .ComputeRateUpdateForOnlineLearningMode(monitor_block,
    225                                                        kTargetSendingRate)
    226                .bps(),
    227            kTargetSendingRate.bps() *
    228                (1 - kInitialDynamicBoundary - kDynamicBoundaryIncrement));
    229 }
    230 
    231 TEST(PccBitrateControllerTest, SlowStartMode) {
    232  std::unique_ptr<MockUtilityFunction> mock_utility_function =
    233      std::make_unique<MockUtilityFunction>();
    234  constexpr double kFirstUtilityFunction = 1000;
    235  EXPECT_CALL(*mock_utility_function, Compute(::testing::_))
    236      .Times(4)
    237      // For first 3 calls we expect to stay in the SLOW_START mode and double
    238      // the sending rate since the utility function increases its value. For
    239      // the last call utility function decreases its value, this means that
    240      // we should not double the sending rate and exit SLOW_START mode.
    241      .WillOnce(::testing::Return(kFirstUtilityFunction))
    242      .WillOnce(::testing::Return(kFirstUtilityFunction + 1))
    243      .WillOnce(::testing::Return(kFirstUtilityFunction + 2))
    244      .WillOnce(::testing::Return(kFirstUtilityFunction + 1));
    245 
    246  PccBitrateController bitrate_controller(
    247      kInitialConversionFactor, kInitialDynamicBoundary,
    248      kDynamicBoundaryIncrement, std::move(mock_utility_function));
    249  std::vector<PccMonitorInterval> monitor_block{PccMonitorInterval(
    250      2 * kTargetSendingRate, kStartTime, kIntervalDuration)};
    251  // To complete collecting feedback within monitor intervals.
    252  monitor_block[0].OnPacketsFeedback(
    253      CreatePacketResults({kStartTime + 3 * kIntervalDuration}, {}, {}));
    254  EXPECT_EQ(
    255      bitrate_controller.ComputeRateUpdateForSlowStartMode(monitor_block[0]),
    256      kTargetSendingRate * 2);
    257  EXPECT_EQ(
    258      bitrate_controller.ComputeRateUpdateForSlowStartMode(monitor_block[0]),
    259      kTargetSendingRate * 2);
    260  EXPECT_EQ(
    261      bitrate_controller.ComputeRateUpdateForSlowStartMode(monitor_block[0]),
    262      kTargetSendingRate * 2);
    263  EXPECT_EQ(
    264      bitrate_controller.ComputeRateUpdateForSlowStartMode(monitor_block[0]),
    265      std::nullopt);
    266 }
    267 
    268 TEST(PccBitrateControllerTest, StepSizeIncrease) {
    269  std::unique_ptr<MockUtilityFunction> mock_utility_function =
    270      std::make_unique<MockUtilityFunction>();
    271  constexpr double kFirstMiUtilityFunction = 0;
    272  const double kSecondMiUtilityFunction =
    273      2 * kTargetSendingRate.bps() * kEpsilon;
    274 
    275  EXPECT_CALL(*mock_utility_function, Compute(::testing::_))
    276      .Times(4)
    277      .WillOnce(::testing::Return(kFirstMiUtilityFunction))
    278      .WillOnce(::testing::Return(kSecondMiUtilityFunction))
    279      .WillOnce(::testing::Return(kFirstMiUtilityFunction))
    280      .WillOnce(::testing::Return(kSecondMiUtilityFunction));
    281  std::vector<PccMonitorInterval> monitor_block{
    282      PccMonitorInterval(kTargetSendingRate * (1 + kEpsilon), kStartTime,
    283                         kIntervalDuration),
    284      PccMonitorInterval(kTargetSendingRate * (1 - kEpsilon),
    285                         kStartTime + kIntervalDuration, kIntervalDuration)};
    286  // To complete collecting feedback within monitor intervals.
    287  monitor_block[0].OnPacketsFeedback(
    288      CreatePacketResults({kStartTime + 3 * kIntervalDuration}, {}, {}));
    289  monitor_block[1].OnPacketsFeedback(
    290      CreatePacketResults({kStartTime + 3 * kIntervalDuration}, {}, {}));
    291 
    292  double gradient = (kFirstMiUtilityFunction - kSecondMiUtilityFunction) /
    293                    (kTargetSendingRate.bps() * 2 * kEpsilon);
    294  PccBitrateController bitrate_controller(
    295      kInitialConversionFactor, kInitialDynamicBoundary,
    296      kDynamicBoundaryIncrement, std::move(mock_utility_function));
    297  // If we are moving in the same direction - the step size should increase.
    298  EXPECT_EQ(bitrate_controller
    299                .ComputeRateUpdateForOnlineLearningMode(monitor_block,
    300                                                        kTargetSendingRate)
    301                .bps(),
    302            kTargetSendingRate.bps() + kInitialConversionFactor * gradient);
    303  EXPECT_EQ(bitrate_controller
    304                .ComputeRateUpdateForOnlineLearningMode(monitor_block,
    305                                                        kTargetSendingRate)
    306                .bps(),
    307            kTargetSendingRate.bps() + 2 * kInitialConversionFactor * gradient);
    308 }
    309 
    310 }  // namespace test
    311 }  // namespace pcc
    312 }  // namespace webrtc