diff --git a/BUILD.gn b/BUILD.gn index d4e89fde83..1be75d3d5e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -40,6 +40,7 @@ if (!build_with_chromium) { if (rtc_include_tests) { deps += [ ":rtc_unittests", + ":slow_tests", ":video_engine_tests", ":webrtc_nonparallel_tests", ":webrtc_perf_tests", @@ -501,6 +502,17 @@ if (rtc_include_tests) { } } + # This runs tests that must run in real time and therefore can take some + # time to execute. They are in a separate executable to avoid making the + # regular unittest suite too slow to run frequently. + rtc_test("slow_tests") { + testonly = true + deps = [ + "modules/congestion_controller/goog_cc:goog_cc_slow_tests", + "test:test_main", + ] + } + # TODO(pbos): Rename test suite, this is no longer "just" for video targets. video_engine_tests_resources = [ "resources/foreman_cif_short.yuv", diff --git a/modules/congestion_controller/goog_cc/BUILD.gn b/modules/congestion_controller/goog_cc/BUILD.gn index 8b34c38f2f..ba71686bdd 100644 --- a/modules/congestion_controller/goog_cc/BUILD.gn +++ b/modules/congestion_controller/goog_cc/BUILD.gn @@ -214,4 +214,40 @@ if (rtc_include_tests) { "//third_party/abseil-cpp/absl/memory", ] } + rtc_source_set("goog_cc_slow_tests") { + testonly = true + + sources = [ + "goog_cc_network_control_slowtest.cc", + ] + if (!build_with_chromium && is_clang) { + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] + } + 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", + "../../../logging:mocks", + "../../../rtc_base:checks", + "../../../rtc_base:rtc_base_approved", + "../../../rtc_base:rtc_base_tests_utils", + "../../../rtc_base/experiments:alr_experiment", + "../../../system_wrappers", + "../../../system_wrappers:field_trial", + "../../../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", + ] + } } 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 new file mode 100644 index 0000000000..912c4553d8 --- /dev/null +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_slowtest.cc @@ -0,0 +1,123 @@ +/* + * 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 "api/transport/goog_cc_factory.h" +#include "test/field_trial.h" +#include "test/gtest.h" +#include "test/scenario/scenario.h" + +namespace webrtc { +namespace test { + +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()); + // Trigger reroute message, but keep transport unchanged. + s.ChangeRoute(route->forward(), {send_net}); + + // 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()); + + s.ChangeRoute(route->forward(), {send_net}); + // 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/"); + 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()); + s.ChangeRoute(route->forward(), {initial_net}); + + // 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. + s.RunFor(TimeDelta::ms(100)); + // 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_NEAR(client->send_bandwidth().kbps(), kNewLinkCapacity.kbps(), 200); +} + +} // namespace test +} // namespace webrtc