Unittests for loss based bandwidth estimation.

Bug: none
Change-Id: I204071683c1c6e28040ea3bce900c4b04108cba7
Reviewed-on: https://webrtc-review.googlesource.com/c/112380
Commit-Queue: Christoffer Rodbro <crodbro@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25844}
diff --git a/modules/bitrate_controller/loss_based_bandwidth_estimation.cc b/modules/bitrate_controller/loss_based_bandwidth_estimation.cc
index 5d7f8aa..f22f970 100644
--- a/modules/bitrate_controller/loss_based_bandwidth_estimation.cc
+++ b/modules/bitrate_controller/loss_based_bandwidth_estimation.cc
@@ -156,9 +156,9 @@
   if (acknowledged_bitrate > acknowledged_bitrate_max_) {
     acknowledged_bitrate_max_ = acknowledged_bitrate;
   } else {
-    acknowledged_bitrate_max_ +=
+    acknowledged_bitrate_max_ -=
         ExponentialUpdate(config_.acknowledged_rate_max_window, time_passed) *
-        (acknowledged_bitrate - acknowledged_bitrate_max_);
+        (acknowledged_bitrate_max_ - acknowledged_bitrate);
   }
 }
 
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
index fecd1b3..071fe09 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
@@ -28,6 +28,58 @@
 const uint32_t kInitialBitrateKbps = 60;
 const DataRate kInitialBitrate = DataRate::kbps(kInitialBitrateKbps);
 const float kDefaultPacingRate = 2.5f;
+
+void UpdatesTargetRateBasedOnLinkCapacity(double loss_rate = 0.0) {
+  Scenario s("googcc_unit/target_capacity", false);
+  SimulatedTimeClientConfig config;
+  config.transport.cc =
+      TransportControllerConfig::CongestionController::kGoogCcFeedback;
+  config.transport.rates.min_rate = DataRate::kbps(10);
+  config.transport.rates.max_rate = DataRate::kbps(1500);
+  config.transport.rates.start_rate = DataRate::kbps(300);
+  NetworkNodeConfig net_conf;
+  auto send_net = s.CreateSimulationNode([loss_rate](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = DataRate::kbps(500);
+    c->simulation.delay = TimeDelta::ms(100);
+    c->simulation.loss_rate = loss_rate;
+    c->update_frequency = TimeDelta::ms(5);
+  });
+  auto ret_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+    c->simulation.delay = TimeDelta::ms(100);
+    c->update_frequency = TimeDelta::ms(5);
+  });
+  StatesPrinter* truth = s.CreatePrinter(
+      "send.truth.txt", TimeDelta::PlusInfinity(), {send_net->ConfigPrinter()});
+  SimulatedTimeClient* client = s.CreateSimulatedTimeClient(
+      "send", config, {PacketStreamConfig()}, {send_net}, {ret_net});
+
+  truth->PrintRow();
+  s.RunFor(TimeDelta::seconds(25));
+  truth->PrintRow();
+  EXPECT_NEAR(client->target_rate_kbps(), 450, 100);
+
+  send_net->UpdateConfig([](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = DataRate::kbps(800);
+    c->simulation.delay = TimeDelta::ms(100);
+  });
+
+  truth->PrintRow();
+  s.RunFor(TimeDelta::seconds(20));
+  truth->PrintRow();
+  EXPECT_NEAR(client->target_rate_kbps(), 750, 150);
+
+  send_net->UpdateConfig([](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = DataRate::kbps(100);
+    c->simulation.delay = TimeDelta::ms(200);
+  });
+  ret_net->UpdateConfig(
+      [](NetworkNodeConfig* c) { c->simulation.delay = TimeDelta::ms(200); });
+
+  truth->PrintRow();
+  s.RunFor(TimeDelta::seconds(30));
+  truth->PrintRow();
+  EXPECT_NEAR(client->target_rate_kbps(), 90, 20);
+}
 }  // namespace
 
 class GoogCcNetworkControllerTest : public ::testing::Test {
@@ -349,54 +401,7 @@
 }
 
 TEST_F(GoogCcNetworkControllerTest, UpdatesTargetRateBasedOnLinkCapacity) {
-  Scenario s("googcc_unit/target_capacity", false);
-  SimulatedTimeClientConfig config;
-  config.transport.cc =
-      TransportControllerConfig::CongestionController::kGoogCcFeedback;
-  config.transport.rates.min_rate = DataRate::kbps(10);
-  config.transport.rates.max_rate = DataRate::kbps(1500);
-  config.transport.rates.start_rate = DataRate::kbps(300);
-  NetworkNodeConfig net_conf;
-  auto send_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = DataRate::kbps(500);
-    c->simulation.delay = TimeDelta::ms(100);
-    c->update_frequency = TimeDelta::ms(5);
-  });
-  auto ret_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
-    c->simulation.delay = TimeDelta::ms(100);
-    c->update_frequency = TimeDelta::ms(5);
-  });
-  StatesPrinter* truth = s.CreatePrinter(
-      "send.truth.txt", TimeDelta::PlusInfinity(), {send_net->ConfigPrinter()});
-  SimulatedTimeClient* client = s.CreateSimulatedTimeClient(
-      "send", config, {PacketStreamConfig()}, {send_net}, {ret_net});
-
-  truth->PrintRow();
-  s.RunFor(TimeDelta::seconds(25));
-  truth->PrintRow();
-  EXPECT_NEAR(client->target_rate_kbps(), 450, 100);
-
-  send_net->UpdateConfig([](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = DataRate::kbps(800);
-    c->simulation.delay = TimeDelta::ms(100);
-  });
-
-  truth->PrintRow();
-  s.RunFor(TimeDelta::seconds(20));
-  truth->PrintRow();
-  EXPECT_NEAR(client->target_rate_kbps(), 750, 150);
-
-  send_net->UpdateConfig([](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = DataRate::kbps(100);
-    c->simulation.delay = TimeDelta::ms(200);
-  });
-  ret_net->UpdateConfig(
-      [](NetworkNodeConfig* c) { c->simulation.delay = TimeDelta::ms(200); });
-
-  truth->PrintRow();
-  s.RunFor(TimeDelta::seconds(30));
-  truth->PrintRow();
-  EXPECT_NEAR(client->target_rate_kbps(), 90, 20);
+  UpdatesTargetRateBasedOnLinkCapacity();
 }
 
 TEST_F(GoogCcNetworkControllerTest, DefaultEstimateVariesInSteadyState) {
@@ -455,5 +460,68 @@
   EXPECT_GT(min_estimate / max_estimate, 0.95);
 }
 
+TEST_F(GoogCcNetworkControllerTest,
+       LossBasedControlUpdatesTargetRateBasedOnLinkCapacity) {
+  ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
+  UpdatesTargetRateBasedOnLinkCapacity(/*loss_rate*/ 0.01);
+}
+
+TEST_F(GoogCcNetworkControllerTest,
+       LossBasedControlDoesModestBackoffToHighLoss) {
+  ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
+  Scenario s("googcc_unit/high_loss_channel", false);
+  SimulatedTimeClientConfig config;
+  config.transport.cc =
+      TransportControllerConfig::CongestionController::kGoogCcFeedback;
+  config.transport.rates.min_rate = DataRate::kbps(10);
+  config.transport.rates.max_rate = DataRate::kbps(1500);
+  config.transport.rates.start_rate = DataRate::kbps(300);
+  NetworkNodeConfig net_conf;
+  auto send_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = DataRate::kbps(2000);
+    c->simulation.delay = TimeDelta::ms(200);
+    c->simulation.loss_rate = 0.1;
+    c->update_frequency = TimeDelta::ms(5);
+  });
+  auto ret_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+    c->simulation.delay = TimeDelta::ms(200);
+    c->update_frequency = TimeDelta::ms(5);
+  });
+  SimulatedTimeClient* client = s.CreateSimulatedTimeClient(
+      "send", config, {PacketStreamConfig()}, {send_net}, {ret_net});
+
+  s.RunFor(TimeDelta::seconds(120));
+  // Without LossBasedControl trial, bandwidth drops to ~10 kbps.
+  EXPECT_GT(client->target_rate_kbps(), 100);
+}
+
+TEST_F(GoogCcNetworkControllerTest, LossBasedEstimatorCapsRateAtModerateLoss) {
+  ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
+  Scenario s("googcc_unit/moderate_loss_channel", false);
+  SimulatedTimeClientConfig config;
+  config.transport.cc =
+      TransportControllerConfig::CongestionController::kGoogCcFeedback;
+  config.transport.rates.min_rate = DataRate::kbps(10);
+  config.transport.rates.max_rate = DataRate::kbps(5000);
+  config.transport.rates.start_rate = DataRate::kbps(300);
+  NetworkNodeConfig net_conf;
+  auto send_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = DataRate::kbps(5000);
+    c->simulation.delay = TimeDelta::ms(100);
+    c->simulation.loss_rate = 0.02;
+    c->update_frequency = TimeDelta::ms(5);
+  });
+  auto ret_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+    c->simulation.delay = TimeDelta::ms(100);
+    c->update_frequency = TimeDelta::ms(5);
+  });
+  SimulatedTimeClient* client = s.CreateSimulatedTimeClient(
+      "send", config, {PacketStreamConfig()}, {send_net}, {ret_net});
+
+  s.RunFor(TimeDelta::seconds(60));
+  // Without LossBasedControl trial, bitrate reaches above 4 mbps.
+  EXPECT_NEAR(client->target_rate_kbps(), 2000, 500);
+}
+
 }  // namespace test
 }  // namespace webrtc
diff --git a/test/scenario/simulated_time.cc b/test/scenario/simulated_time.cc
index 9759533..becd793 100644
--- a/test/scenario/simulated_time.cc
+++ b/test/scenario/simulated_time.cc
@@ -229,7 +229,8 @@
                                                     it->second});
         receive_times_.erase(it);
       }
-      if (receive_times_.size() >= RawFeedbackReportPacket::MAX_FEEDBACKS) {
+      if (report.receive_times.size() >=
+          RawFeedbackReportPacket::MAX_FEEDBACKS) {
         return_node_->TryDeliverPacket(FeedbackToBuffer(report),
                                        return_receiver_id_, at_time);
         report = SimpleFeedbackReportPacket();