Using simulated time for GoogCC tests.

Bug: webrtc:10365
Change-Id: I482e544f1585fdb54dc49740ba81870104dd58a0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/130509
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27468}
diff --git a/modules/congestion_controller/goog_cc/BUILD.gn b/modules/congestion_controller/goog_cc/BUILD.gn
index 0c67a7d..0124514 100644
--- a/modules/congestion_controller/goog_cc/BUILD.gn
+++ b/modules/congestion_controller/goog_cc/BUILD.gn
@@ -254,36 +254,8 @@
       "//third_party/abseil-cpp/absl/memory",
     ]
   }
-  rtc_source_set("goog_cc_slow_tests") {
-    testonly = true
 
-    sources = [
-      "goog_cc_network_control_slowtest.cc",
-    ]
-    deps = [
-      ":alr_detector",
-      ":delay_based_bwe",
-      ":estimators",
-      ":goog_cc",
-      ":probe_controller",
-      ":pushback_controller",
-      "../../../api/transport:goog_cc",
-      "../../../api/transport:network_control",
-      "../../../api/transport:network_control_test",
-      "../../../api/transport:webrtc_key_value_config",
-      "../../../logging:mocks",
-      "../../../rtc_base:checks",
-      "../../../rtc_base:rtc_base_approved",
-      "../../../rtc_base/experiments:alr_experiment",
-      "../../../system_wrappers",
-      "../../../test:field_trial",
-      "../../../test:test_support",
-      "../../../test/scenario",
-      "../../pacing",
-      "../../remote_bitrate_estimator",
-      "../../rtp_rtcp:rtp_rtcp_format",
-      "//testing/gmock",
-      "//third_party/abseil-cpp/absl/memory",
-    ]
+  # TODO(srte): Remove this target when dependency in root BUILD is gone.
+  rtc_source_set("goog_cc_slow_tests") {
   }
 }
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_slowtest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_slowtest.cc
deleted file mode 100644
index 67ab99e..0000000
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control_slowtest.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *  Copyright (c) 2018 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 <queue>
-
-#include "api/transport/goog_cc_factory.h"
-#include "test/field_trial.h"
-#include "test/gtest.h"
-#include "test/scenario/scenario.h"
-
-namespace webrtc {
-namespace test {
-namespace {
-// Count dips from a constant high bandwidth level within a short window.
-int CountBandwidthDips(std::queue<DataRate> bandwidth_history,
-                       DataRate threshold) {
-  if (bandwidth_history.empty())
-    return true;
-  DataRate first = bandwidth_history.front();
-  bandwidth_history.pop();
-
-  int dips = 0;
-  bool state_high = true;
-  while (!bandwidth_history.empty()) {
-    if (bandwidth_history.front() + threshold < first && state_high) {
-      ++dips;
-      state_high = false;
-    } else if (bandwidth_history.front() == first) {
-      state_high = true;
-    } else if (bandwidth_history.front() > first) {
-      // If this is toggling we will catch it later when front becomes first.
-      state_high = false;
-    }
-    bandwidth_history.pop();
-  }
-  return dips;
-}
-}  // namespace
-
-TEST(GoogCcNetworkControllerTest, MaintainsLowRateInSafeResetTrial) {
-  const DataRate kLinkCapacity = DataRate::kbps(200);
-  const DataRate kStartRate = DataRate::kbps(300);
-
-  ScopedFieldTrials trial("WebRTC-Bwe-SafeResetOnRouteChange/Enabled/");
-  Scenario s("googcc_unit/safe_reset_low", true);
-  auto* send_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = kLinkCapacity;
-    c->simulation.delay = TimeDelta::ms(10);
-  });
-  // TODO(srte): replace with SimulatedTimeClient when it supports probing.
-  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
-    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
-    c->transport.rates.start_rate = kStartRate;
-  });
-  auto* route = s.CreateRoutes(client, {send_net},
-                               s.CreateClient("return", CallClientConfig()),
-                               {s.CreateSimulationNode(NetworkNodeConfig())});
-  s.CreateVideoStream(route->forward(), VideoStreamConfig());
-  // Allow the controller to stabilize.
-  s.RunFor(TimeDelta::ms(500));
-  EXPECT_NEAR(client->send_bandwidth().kbps(), kLinkCapacity.kbps(), 50);
-  s.ChangeRoute(route->forward(), {send_net});
-  // Allow new settings to propagate.
-  s.RunFor(TimeDelta::ms(100));
-  // Under the trial, the target should be unchanged for low rates.
-  EXPECT_NEAR(client->send_bandwidth().kbps(), kLinkCapacity.kbps(), 50);
-}
-
-TEST(GoogCcNetworkControllerTest, CutsHighRateInSafeResetTrial) {
-  const DataRate kLinkCapacity = DataRate::kbps(1000);
-  const DataRate kStartRate = DataRate::kbps(300);
-
-  ScopedFieldTrials trial("WebRTC-Bwe-SafeResetOnRouteChange/Enabled/");
-  Scenario s("googcc_unit/safe_reset_high_cut", true);
-  auto send_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = kLinkCapacity;
-    c->simulation.delay = TimeDelta::ms(50);
-  });
-  // TODO(srte): replace with SimulatedTimeClient when it supports probing.
-  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
-    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
-    c->transport.rates.start_rate = kStartRate;
-  });
-  auto* route = s.CreateRoutes(client, {send_net},
-                               s.CreateClient("return", CallClientConfig()),
-                               {s.CreateSimulationNode(NetworkNodeConfig())});
-  s.CreateVideoStream(route->forward(), VideoStreamConfig());
-  // Allow the controller to stabilize.
-  s.RunFor(TimeDelta::ms(500));
-  EXPECT_NEAR(client->send_bandwidth().kbps(), kLinkCapacity.kbps(), 300);
-  s.ChangeRoute(route->forward(), {send_net});
-  // Allow new settings to propagate.
-  s.RunFor(TimeDelta::ms(50));
-  // Under the trial, the target should be reset from high values.
-  EXPECT_NEAR(client->send_bandwidth().kbps(), kStartRate.kbps(), 30);
-}
-
-TEST(GoogCcNetworkControllerTest, DetectsHighRateInSafeResetTrial) {
-  ScopedFieldTrials trial(
-      "WebRTC-Bwe-SafeResetOnRouteChange/Enabled,ack/"
-      "WebRTC-Bwe-ProbeRateFallback/Enabled/");
-  const DataRate kInitialLinkCapacity = DataRate::kbps(200);
-  const DataRate kNewLinkCapacity = DataRate::kbps(800);
-  const DataRate kStartRate = DataRate::kbps(300);
-
-  Scenario s("googcc_unit/safe_reset_high_detect", true);
-  auto* initial_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = kInitialLinkCapacity;
-    c->simulation.delay = TimeDelta::ms(50);
-  });
-  auto* new_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = kNewLinkCapacity;
-    c->simulation.delay = TimeDelta::ms(50);
-  });
-  // TODO(srte): replace with SimulatedTimeClient when it supports probing.
-  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
-    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
-    c->transport.rates.start_rate = kStartRate;
-  });
-  auto* route = s.CreateRoutes(client, {initial_net},
-                               s.CreateClient("return", CallClientConfig()),
-                               {s.CreateSimulationNode(NetworkNodeConfig())});
-  s.CreateVideoStream(route->forward(), VideoStreamConfig());
-  // Allow the controller to stabilize.
-  s.RunFor(TimeDelta::ms(1000));
-  EXPECT_NEAR(client->send_bandwidth().kbps(), kInitialLinkCapacity.kbps(), 50);
-  s.ChangeRoute(route->forward(), {new_net});
-  // Allow new settings to propagate, but not probes to be received.
-  s.RunFor(TimeDelta::ms(50));
-  // Under the field trial, the target rate should be unchanged since it's lower
-  // than the starting rate.
-  EXPECT_NEAR(client->send_bandwidth().kbps(), kInitialLinkCapacity.kbps(), 50);
-  // However, probing should have made us detect the higher rate.
-  s.RunFor(TimeDelta::ms(2000));
-  EXPECT_GT(client->send_bandwidth().kbps(), kNewLinkCapacity.kbps() - 300);
-}
-
-TEST(GoogCcNetworkControllerTest,
-     TargetRateReducedOnPacingBufferBuildupInTrial) {
-  // Configure strict pacing to ensure build-up.
-  ScopedFieldTrials trial(
-      "WebRTC-CongestionWindowPushback/Enabled/WebRTC-CwndExperiment/"
-      "Enabled-100/WebRTC-Video-Pacing/factor:1.0/"
-      "WebRTC-AddPacingToCongestionWindowPushback/Enabled/");
-
-  const DataRate kLinkCapacity = DataRate::kbps(1000);
-  const DataRate kStartRate = DataRate::kbps(1000);
-
-  Scenario s("googcc_unit/pacing_buffer_buildup", true);
-  auto* net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = kLinkCapacity;
-    c->simulation.delay = TimeDelta::ms(50);
-  });
-  // TODO(srte): replace with SimulatedTimeClient when it supports pacing.
-  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
-    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
-    c->transport.rates.start_rate = kStartRate;
-  });
-  auto* route = s.CreateRoutes(client, {net},
-                               s.CreateClient("return", CallClientConfig()),
-                               {s.CreateSimulationNode(NetworkNodeConfig())});
-  s.CreateVideoStream(route->forward(), VideoStreamConfig());
-  // Allow some time for the buffer to build up.
-  s.RunFor(TimeDelta::seconds(5));
-
-  // Without trial, pacer delay reaches ~250 ms.
-  EXPECT_LT(client->GetStats().pacer_delay_ms, 150);
-}
-
-TEST(GoogCcNetworkControllerTest, NoBandwidthTogglingInLossControlTrial) {
-  ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
-  Scenario s("googcc_unit/no_toggling", true);
-  auto* send_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = DataRate::kbps(2000);
-    c->simulation.loss_rate = 0.2;
-    c->simulation.delay = TimeDelta::ms(10);
-  });
-
-  // TODO(srte): replace with SimulatedTimeClient when it supports probing.
-  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
-    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
-    c->transport.rates.start_rate = DataRate::kbps(300);
-  });
-  auto* route = s.CreateRoutes(client, {send_net},
-                               s.CreateClient("return", CallClientConfig()),
-                               {s.CreateSimulationNode(NetworkNodeConfig())});
-  s.CreateVideoStream(route->forward(), VideoStreamConfig());
-  // Allow the controller to initialize.
-  s.RunFor(TimeDelta::ms(250));
-
-  std::queue<DataRate> bandwidth_history;
-  const TimeDelta step = TimeDelta::ms(50);
-  for (TimeDelta time = TimeDelta::Zero(); time < TimeDelta::ms(2000);
-       time += step) {
-    s.RunFor(step);
-    const TimeDelta window = TimeDelta::ms(500);
-    if (bandwidth_history.size() >= window / step)
-      bandwidth_history.pop();
-    bandwidth_history.push(client->send_bandwidth());
-    EXPECT_LT(CountBandwidthDips(bandwidth_history, DataRate::kbps(100)), 2);
-  }
-}
-
-TEST(GoogCcNetworkControllerTest, NoRttBackoffCollapseWhenVideoStops) {
-  ScopedFieldTrials trial("WebRTC-Bwe-MaxRttLimit/limit:2s/");
-  Scenario s("googcc_unit/rttbackoff_video_stop", true);
-  auto* send_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
-    c->simulation.bandwidth = DataRate::kbps(2000);
-    c->simulation.delay = TimeDelta::ms(100);
-  });
-
-  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
-    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
-    c->transport.rates.start_rate = DataRate::kbps(1000);
-  });
-  auto* route = s.CreateRoutes(client, {send_net},
-                               s.CreateClient("return", CallClientConfig()),
-                               {s.CreateSimulationNode(NetworkNodeConfig())});
-  auto* video = s.CreateVideoStream(route->forward(), VideoStreamConfig());
-  // Allow the controller to initialize, then stop video.
-  s.RunFor(TimeDelta::seconds(1));
-  video->send()->Stop();
-  s.RunFor(TimeDelta::seconds(4));
-  EXPECT_GT(client->send_bandwidth().kbps(), 1000);
-}
-
-}  // namespace test
-}  // namespace webrtc
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 1528729..000ff9e 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
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <queue>
+
 #include "api/transport/goog_cc_factory.h"
 #include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
 #include "test/field_trial.h"
@@ -23,6 +25,30 @@
 namespace webrtc {
 namespace test {
 namespace {
+// Count dips from a constant high bandwidth level within a short window.
+int CountBandwidthDips(std::queue<DataRate> bandwidth_history,
+                       DataRate threshold) {
+  if (bandwidth_history.empty())
+    return true;
+  DataRate first = bandwidth_history.front();
+  bandwidth_history.pop();
+
+  int dips = 0;
+  bool state_high = true;
+  while (!bandwidth_history.empty()) {
+    if (bandwidth_history.front() + threshold < first && state_high) {
+      ++dips;
+      state_high = false;
+    } else if (bandwidth_history.front() == first) {
+      state_high = true;
+    } else if (bandwidth_history.front() > first) {
+      // If this is toggling we will catch it later when front becomes first.
+      state_high = false;
+    }
+    bandwidth_history.pop();
+  }
+  return dips;
+}
 
 const uint32_t kInitialBitrateKbps = 60;
 const DataRate kInitialBitrate = DataRate::kbps(kInitialBitrateKbps);
@@ -505,5 +531,192 @@
   EXPECT_LT(client->target_rate_kbps(), 3000);
 }
 
+TEST_F(GoogCcNetworkControllerTest, MaintainsLowRateInSafeResetTrial) {
+  const DataRate kLinkCapacity = DataRate::kbps(200);
+  const DataRate kStartRate = DataRate::kbps(300);
+
+  ScopedFieldTrials trial("WebRTC-Bwe-SafeResetOnRouteChange/Enabled/");
+  Scenario s("googcc_unit/safe_reset_low");
+  auto* send_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = kLinkCapacity;
+    c->simulation.delay = TimeDelta::ms(10);
+  });
+  // TODO(srte): replace with SimulatedTimeClient when it supports probing.
+  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
+    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
+    c->transport.rates.start_rate = kStartRate;
+  });
+  auto* route = s.CreateRoutes(client, {send_net},
+                               s.CreateClient("return", CallClientConfig()),
+                               {s.CreateSimulationNode(NetworkNodeConfig())});
+  s.CreateVideoStream(route->forward(), VideoStreamConfig());
+  // Allow the controller to stabilize.
+  s.RunFor(TimeDelta::ms(500));
+  EXPECT_NEAR(client->send_bandwidth().kbps(), kLinkCapacity.kbps(), 50);
+  s.ChangeRoute(route->forward(), {send_net});
+  // Allow new settings to propagate.
+  s.RunFor(TimeDelta::ms(100));
+  // Under the trial, the target should be unchanged for low rates.
+  EXPECT_NEAR(client->send_bandwidth().kbps(), kLinkCapacity.kbps(), 50);
+}
+
+TEST_F(GoogCcNetworkControllerTest, CutsHighRateInSafeResetTrial) {
+  const DataRate kLinkCapacity = DataRate::kbps(1000);
+  const DataRate kStartRate = DataRate::kbps(300);
+
+  ScopedFieldTrials trial("WebRTC-Bwe-SafeResetOnRouteChange/Enabled/");
+  Scenario s("googcc_unit/safe_reset_high_cut");
+  auto send_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = kLinkCapacity;
+    c->simulation.delay = TimeDelta::ms(50);
+  });
+  // TODO(srte): replace with SimulatedTimeClient when it supports probing.
+  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
+    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
+    c->transport.rates.start_rate = kStartRate;
+  });
+  auto* route = s.CreateRoutes(client, {send_net},
+                               s.CreateClient("return", CallClientConfig()),
+                               {s.CreateSimulationNode(NetworkNodeConfig())});
+  s.CreateVideoStream(route->forward(), VideoStreamConfig());
+  // Allow the controller to stabilize.
+  s.RunFor(TimeDelta::ms(500));
+  EXPECT_NEAR(client->send_bandwidth().kbps(), kLinkCapacity.kbps(), 300);
+  s.ChangeRoute(route->forward(), {send_net});
+  // Allow new settings to propagate.
+  s.RunFor(TimeDelta::ms(50));
+  // Under the trial, the target should be reset from high values.
+  EXPECT_NEAR(client->send_bandwidth().kbps(), kStartRate.kbps(), 30);
+}
+
+TEST_F(GoogCcNetworkControllerTest, DetectsHighRateInSafeResetTrial) {
+  ScopedFieldTrials trial(
+      "WebRTC-Bwe-SafeResetOnRouteChange/Enabled,ack/"
+      "WebRTC-Bwe-ProbeRateFallback/Enabled/");
+  const DataRate kInitialLinkCapacity = DataRate::kbps(200);
+  const DataRate kNewLinkCapacity = DataRate::kbps(800);
+  const DataRate kStartRate = DataRate::kbps(300);
+
+  Scenario s("googcc_unit/safe_reset_high_detect");
+  auto* initial_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = kInitialLinkCapacity;
+    c->simulation.delay = TimeDelta::ms(50);
+  });
+  auto* new_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = kNewLinkCapacity;
+    c->simulation.delay = TimeDelta::ms(50);
+  });
+  // TODO(srte): replace with SimulatedTimeClient when it supports probing.
+  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
+    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
+    c->transport.rates.start_rate = kStartRate;
+  });
+  auto* route = s.CreateRoutes(client, {initial_net},
+                               s.CreateClient("return", CallClientConfig()),
+                               {s.CreateSimulationNode(NetworkNodeConfig())});
+  s.CreateVideoStream(route->forward(), VideoStreamConfig());
+  // Allow the controller to stabilize.
+  s.RunFor(TimeDelta::ms(1000));
+  EXPECT_NEAR(client->send_bandwidth().kbps(), kInitialLinkCapacity.kbps(), 50);
+  s.ChangeRoute(route->forward(), {new_net});
+  // Allow new settings to propagate, but not probes to be received.
+  s.RunFor(TimeDelta::ms(50));
+  // Under the field trial, the target rate should be unchanged since it's lower
+  // than the starting rate.
+  EXPECT_NEAR(client->send_bandwidth().kbps(), kInitialLinkCapacity.kbps(), 50);
+  // However, probing should have made us detect the higher rate.
+  s.RunFor(TimeDelta::ms(2000));
+  EXPECT_GT(client->send_bandwidth().kbps(), kNewLinkCapacity.kbps() - 300);
+}
+
+TEST_F(GoogCcNetworkControllerTest,
+       TargetRateReducedOnPacingBufferBuildupInTrial) {
+  // Configure strict pacing to ensure build-up.
+  ScopedFieldTrials trial(
+      "WebRTC-CongestionWindowPushback/Enabled/WebRTC-CwndExperiment/"
+      "Enabled-100/WebRTC-Video-Pacing/factor:1.0/"
+      "WebRTC-AddPacingToCongestionWindowPushback/Enabled/");
+
+  const DataRate kLinkCapacity = DataRate::kbps(1000);
+  const DataRate kStartRate = DataRate::kbps(1000);
+
+  Scenario s("googcc_unit/pacing_buffer_buildup");
+  auto* net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = kLinkCapacity;
+    c->simulation.delay = TimeDelta::ms(50);
+  });
+  // TODO(srte): replace with SimulatedTimeClient when it supports pacing.
+  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
+    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
+    c->transport.rates.start_rate = kStartRate;
+  });
+  auto* route = s.CreateRoutes(client, {net},
+                               s.CreateClient("return", CallClientConfig()),
+                               {s.CreateSimulationNode(NetworkNodeConfig())});
+  s.CreateVideoStream(route->forward(), VideoStreamConfig());
+  // Allow some time for the buffer to build up.
+  s.RunFor(TimeDelta::seconds(5));
+
+  // Without trial, pacer delay reaches ~250 ms.
+  EXPECT_LT(client->GetStats().pacer_delay_ms, 150);
+}
+
+TEST_F(GoogCcNetworkControllerTest, NoBandwidthTogglingInLossControlTrial) {
+  ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
+  Scenario s("googcc_unit/no_toggling");
+  auto* send_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = DataRate::kbps(2000);
+    c->simulation.loss_rate = 0.2;
+    c->simulation.delay = TimeDelta::ms(10);
+  });
+
+  // TODO(srte): replace with SimulatedTimeClient when it supports probing.
+  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
+    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
+    c->transport.rates.start_rate = DataRate::kbps(300);
+  });
+  auto* route = s.CreateRoutes(client, {send_net},
+                               s.CreateClient("return", CallClientConfig()),
+                               {s.CreateSimulationNode(NetworkNodeConfig())});
+  s.CreateVideoStream(route->forward(), VideoStreamConfig());
+  // Allow the controller to initialize.
+  s.RunFor(TimeDelta::ms(250));
+
+  std::queue<DataRate> bandwidth_history;
+  const TimeDelta step = TimeDelta::ms(50);
+  for (TimeDelta time = TimeDelta::Zero(); time < TimeDelta::ms(2000);
+       time += step) {
+    s.RunFor(step);
+    const TimeDelta window = TimeDelta::ms(500);
+    if (bandwidth_history.size() >= window / step)
+      bandwidth_history.pop();
+    bandwidth_history.push(client->send_bandwidth());
+    EXPECT_LT(CountBandwidthDips(bandwidth_history, DataRate::kbps(100)), 2);
+  }
+}
+
+TEST_F(GoogCcNetworkControllerTest, NoRttBackoffCollapseWhenVideoStops) {
+  ScopedFieldTrials trial("WebRTC-Bwe-MaxRttLimit/limit:2s/");
+  Scenario s("googcc_unit/rttbackoff_video_stop");
+  auto* send_net = s.CreateSimulationNode([&](NetworkNodeConfig* c) {
+    c->simulation.bandwidth = DataRate::kbps(2000);
+    c->simulation.delay = TimeDelta::ms(100);
+  });
+
+  auto* client = s.CreateClient("send", [&](CallClientConfig* c) {
+    c->transport.cc = TransportControllerConfig::CongestionController::kGoogCc;
+    c->transport.rates.start_rate = DataRate::kbps(1000);
+  });
+  auto* route = s.CreateRoutes(client, {send_net},
+                               s.CreateClient("return", CallClientConfig()),
+                               {s.CreateSimulationNode(NetworkNodeConfig())});
+  auto* video = s.CreateVideoStream(route->forward(), VideoStreamConfig());
+  // Allow the controller to initialize, then stop video.
+  s.RunFor(TimeDelta::seconds(1));
+  video->send()->Stop();
+  s.RunFor(TimeDelta::seconds(4));
+  EXPECT_GT(client->send_bandwidth().kbps(), 1000);
+}
+
 }  // namespace test
 }  // namespace webrtc
diff --git a/test/scenario/scenario.cc b/test/scenario/scenario.cc
index 54639de..f4c4b92 100644
--- a/test/scenario/scenario.cc
+++ b/test/scenario/scenario.cc
@@ -56,9 +56,11 @@
 }
 
 Scenario::Scenario()
-    : Scenario(std::unique_ptr<LogWriterFactoryInterface>(), true) {}
+    : Scenario(std::unique_ptr<LogWriterFactoryInterface>(),
+               /*real_time=*/false) {}
 
-Scenario::Scenario(std::string file_name) : Scenario(file_name, true) {}
+Scenario::Scenario(std::string file_name)
+    : Scenario(file_name, /*real_time=*/false) {}
 
 Scenario::Scenario(std::string file_name, bool real_time)
     : Scenario(GetScenarioLogManager(file_name), real_time) {}