diff --git a/api/BUILD.gn b/api/BUILD.gn index a1969cab47..d95f749da9 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -538,6 +538,7 @@ rtc_source_set("network_emulation_manager_api") { ] deps = [ ":simulated_network_api", + ":time_controller", "../call:simulated_network", "../rtc_base", "test/network_emulation", @@ -547,6 +548,24 @@ rtc_source_set("network_emulation_manager_api") { ] } +rtc_source_set("time_controller") { + visibility = [ "*" ] + sources = [ + "test/time_controller.cc", + "test/time_controller.h", + ] + + deps = [ + "../modules/utility", + "../rtc_base", + "../rtc_base/synchronization:yield_policy", + "../system_wrappers", + "task_queue", + "units:time_delta", + "units:timestamp", + ] +} + rtc_source_set("fec_controller_api") { visibility = [ "*" ] sources = [ @@ -913,29 +932,6 @@ if (rtc_include_tests) { ] } - rtc_library("time_controller") { - visibility = [ "*" ] - testonly = true - sources = [ "test/time_controller.h" ] - - deps = [ - "../modules:module_api", - "../modules/utility:utility", - "../rtc_base", - "../rtc_base:rtc_base_tests_utils", - "../rtc_base:rtc_event", - "../rtc_base/synchronization:sequence_checker", - "../rtc_base/synchronization:yield_policy", - "../rtc_base/task_utils:to_queued_task", - "../system_wrappers", - "task_queue", - "task_queue:default_task_queue_factory", - "units:time_delta", - "units:timestamp", - "//third_party/abseil-cpp/absl/strings", - ] - } - rtc_library("create_time_controller") { visibility = [ "*" ] testonly = true diff --git a/api/test/create_network_emulation_manager.cc b/api/test/create_network_emulation_manager.cc index 72efec2ad2..089a2f8a86 100644 --- a/api/test/create_network_emulation_manager.cc +++ b/api/test/create_network_emulation_manager.cc @@ -17,8 +17,9 @@ namespace webrtc { -std::unique_ptr CreateNetworkEmulationManager() { - return std::make_unique(); +std::unique_ptr CreateNetworkEmulationManager( + TimeMode mode) { + return std::make_unique(mode); } } // namespace webrtc diff --git a/api/test/create_network_emulation_manager.h b/api/test/create_network_emulation_manager.h index 747da1cb54..c57c34874c 100644 --- a/api/test/create_network_emulation_manager.h +++ b/api/test/create_network_emulation_manager.h @@ -18,7 +18,8 @@ namespace webrtc { -std::unique_ptr CreateNetworkEmulationManager(); +std::unique_ptr CreateNetworkEmulationManager( + TimeMode mode = TimeMode::kRealTime); } // namespace webrtc diff --git a/api/test/network_emulation_manager.h b/api/test/network_emulation_manager.h index 4e5379f68b..a04767019b 100644 --- a/api/test/network_emulation_manager.h +++ b/api/test/network_emulation_manager.h @@ -16,6 +16,7 @@ #include "api/test/network_emulation/network_emulation_interfaces.h" #include "api/test/simulated_network.h" +#include "api/test/time_controller.h" #include "api/units/timestamp.h" #include "rtc_base/network.h" @@ -69,6 +70,8 @@ class EmulatedNetworkManagerInterface { std::function stats_callback) const = 0; }; +enum class TimeMode { kRealTime, kSimulated }; + // Provides an API for creating and configuring emulated network layer. // All objects returned by this API are owned by NetworkEmulationManager itself // and will be deleted when manager will be deleted. @@ -103,6 +106,8 @@ class NetworkEmulationManager { }; virtual ~NetworkEmulationManager() = default; + virtual TimeController* time_controller() = 0; + // Creates an emulated network node, which represents single network in // the emulated network layer. virtual EmulatedNetworkNode* CreateEmulatedNode( diff --git a/api/test/time_controller.cc b/api/test/time_controller.cc new file mode 100644 index 0000000000..26fe69cce1 --- /dev/null +++ b/api/test/time_controller.cc @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020 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/test/time_controller.h" + +namespace webrtc { +bool TimeController::Wait(const std::function& done, + TimeDelta max_duration) { + // Step size is chosen to be short enough to not significantly affect latency + // in real time tests while being long enough to avoid adding too much load to + // the system. + const auto kStep = TimeDelta::ms(5); + for (auto elapsed = TimeDelta::Zero(); elapsed < max_duration; + elapsed += kStep) { + if (done()) + return true; + AdvanceTime(kStep); + } + return done(); +} +} // namespace webrtc diff --git a/api/test/time_controller.h b/api/test/time_controller.h index 6c47e91575..6d09481660 100644 --- a/api/test/time_controller.h +++ b/api/test/time_controller.h @@ -23,7 +23,6 @@ #include "system_wrappers/include/clock.h" namespace webrtc { - // Interface for controlling time progress. This allows us to execute test code // in either real time or simulated time by using different implementation of // this interface. @@ -51,6 +50,10 @@ class TimeController { // Allow task queues and process threads created by this instance to execute // for the given |duration|. virtual void AdvanceTime(TimeDelta duration) = 0; + + // Waits until done() == true, polling done() in small time intervals. + bool Wait(const std::function& done, + TimeDelta max_duration = TimeDelta::seconds(5)); }; // Interface for telling time, scheduling an event to fire at a particular time, diff --git a/rtc_base/thread.h b/rtc_base/thread.h index 77aff611f9..d08c3bd09c 100644 --- a/rtc_base/thread.h +++ b/rtc_base/thread.h @@ -425,6 +425,21 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase { #endif protected: + class CurrentThreadSetter : CurrentTaskQueueSetter { + public: + explicit CurrentThreadSetter(Thread* thread) + : CurrentTaskQueueSetter(thread), + manager_(rtc::ThreadManager::Instance()), + previous_(manager_->CurrentThread()) { + manager_->ChangeCurrentThreadForTest(thread); + } + ~CurrentThreadSetter() { manager_->ChangeCurrentThreadForTest(previous_); } + + private: + rtc::ThreadManager* const manager_; + rtc::Thread* const previous_; + }; + // DelayedMessage goes into a priority queue, sorted by trigger time. Messages // with the same trigger time are processed in num_ (FIFO) order. class DelayedMessage { diff --git a/test/network/cross_traffic_unittest.cc b/test/network/cross_traffic_unittest.cc index 52bbd48c1a..4bf19845c0 100644 --- a/test/network/cross_traffic_unittest.cc +++ b/test/network/cross_traffic_unittest.cc @@ -113,8 +113,7 @@ TEST(CrossTrafficTest, RandomWalkCrossTraffic) { } TEST(TcpMessageRouteTest, DeliveredOnLossyNetwork) { - GlobalSimulatedTimeController time(Timestamp::seconds(0)); - NetworkEmulationManagerImpl net(&time); + NetworkEmulationManagerImpl net(TimeMode::kSimulated); BuiltInNetworkBehaviorConfig send; // 800 kbps means that the 100 kB message would be delivered in ca 1 second // under ideal conditions and no overhead. @@ -134,17 +133,16 @@ TEST(TcpMessageRouteTest, DeliveredOnLossyNetwork) { constexpr size_t kMessageSize = 100000; tcp_route->SendMessage(kMessageSize, [&] { - RTC_LOG(LS_INFO) << "Received at " - << ToString(time.GetClock()->CurrentTime()); + RTC_LOG(LS_INFO) << "Received at " << ToString(net.Now()); deliver_count++; }); // If there was no loss, we would have delivered the message in ca 1 second, // with 50% it should take much longer. - time.AdvanceTime(TimeDelta::seconds(5)); + net.time_controller()->AdvanceTime(TimeDelta::seconds(5)); ASSERT_EQ(deliver_count, 0); // But given enough time the messsage will be delivered, but only once. - time.AdvanceTime(TimeDelta::seconds(60)); + net.time_controller()->AdvanceTime(TimeDelta::seconds(60)); EXPECT_EQ(deliver_count, 1); } diff --git a/test/network/feedback_generator.cc b/test/network/feedback_generator.cc index 3ae6fb2086..f2e345f6b2 100644 --- a/test/network/feedback_generator.cc +++ b/test/network/feedback_generator.cc @@ -17,8 +17,7 @@ namespace webrtc { FeedbackGeneratorImpl::FeedbackGeneratorImpl( FeedbackGeneratorImpl::Config config) : conf_(config), - time_controller_{Timestamp::seconds(100000)}, - net_{&time_controller_}, + net_(TimeMode::kSimulated), send_link_{new SimulatedNetwork(conf_.send_link)}, ret_link_{new SimulatedNetwork(conf_.return_link)}, route_(this, @@ -28,11 +27,11 @@ FeedbackGeneratorImpl::FeedbackGeneratorImpl( {net_.CreateEmulatedNode(absl::WrapUnique(ret_link_))})) {} Timestamp FeedbackGeneratorImpl::Now() { - return time_controller_.GetClock()->CurrentTime(); + return net_.Now(); } void FeedbackGeneratorImpl::Sleep(TimeDelta duration) { - time_controller_.AdvanceTime(duration); + net_.time_controller()->AdvanceTime(duration); } void FeedbackGeneratorImpl::SendPacket(size_t size) { diff --git a/test/network/feedback_generator.h b/test/network/feedback_generator.h index afc306892a..98ac01c7a6 100644 --- a/test/network/feedback_generator.h +++ b/test/network/feedback_generator.h @@ -44,7 +44,6 @@ class FeedbackGeneratorImpl private: Config conf_; - GlobalSimulatedTimeController time_controller_; ::webrtc::test::NetworkEmulationManagerImpl net_; SimulatedNetwork* const send_link_; SimulatedNetwork* const ret_link_; diff --git a/test/network/network_emulation_manager.cc b/test/network/network_emulation_manager.cc index 494e885fc2..caa950e0bd 100644 --- a/test/network/network_emulation_manager.cc +++ b/test/network/network_emulation_manager.cc @@ -18,6 +18,7 @@ #include "call/simulated_network.h" #include "rtc_base/fake_network.h" #include "test/time_controller/real_time_controller.h" +#include "test/time_controller/simulated_time_controller.h" namespace webrtc { namespace test { @@ -27,18 +28,27 @@ namespace { constexpr uint32_t kMinIPv4Address = 0xC0A80000; // uint32_t representation of 192.168.255.255 address constexpr uint32_t kMaxIPv4Address = 0xC0A8FFFF; + +std::unique_ptr CreateTimeController(TimeMode mode) { + switch (mode) { + case TimeMode::kRealTime: + return std::make_unique(); + case TimeMode::kSimulated: + // Using an offset of 100000 to get nice fixed width and readable + // timestamps in typical test scenarios. + const Timestamp kSimulatedStartTime = Timestamp::seconds(100000); + return std::make_unique( + kSimulatedStartTime); + } +} } // namespace -NetworkEmulationManagerImpl::NetworkEmulationManagerImpl() - : NetworkEmulationManagerImpl(GlobalRealTimeController()) {} - -NetworkEmulationManagerImpl::NetworkEmulationManagerImpl( - TimeController* time_controller) - : time_controller_(time_controller), - clock_(time_controller->GetClock()), +NetworkEmulationManagerImpl::NetworkEmulationManagerImpl(TimeMode mode) + : time_controller_(CreateTimeController(mode)), + clock_(time_controller_->GetClock()), next_node_id_(1), next_ip4_address_(kMinIPv4Address), - task_queue_(time_controller->GetTaskQueueFactory()->CreateTaskQueue( + task_queue_(time_controller_->GetTaskQueueFactory()->CreateTaskQueue( "NetworkEmulation", TaskQueueFactory::Priority::NORMAL)) {} @@ -266,7 +276,7 @@ NetworkEmulationManagerImpl::CreateEmulatedNetworkManagerInterface( auto endpoints_container = std::make_unique(endpoint_impls); auto network_manager = std::make_unique( - time_controller_, &task_queue_, endpoints_container.get()); + time_controller_.get(), &task_queue_, endpoints_container.get()); for (auto* endpoint : endpoints) { // Associate endpoint with network manager. bool insertion_result = diff --git a/test/network/network_emulation_manager.h b/test/network/network_emulation_manager.h index 25c8050aab..2b33fa1575 100644 --- a/test/network/network_emulation_manager.h +++ b/test/network/network_emulation_manager.h @@ -39,8 +39,7 @@ namespace test { class NetworkEmulationManagerImpl : public NetworkEmulationManager { public: - NetworkEmulationManagerImpl(); - explicit NetworkEmulationManagerImpl(TimeController* time_controller); + explicit NetworkEmulationManagerImpl(TimeMode mode); ~NetworkEmulationManagerImpl(); EmulatedNetworkNode* CreateEmulatedNode( @@ -84,11 +83,13 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager { EmulatedNetworkManagerInterface* CreateEmulatedNetworkManagerInterface( const std::vector& endpoints) override; - private: - absl::optional GetNextIPv4Address(); + TimeController* time_controller() override { return time_controller_.get(); } + Timestamp Now() const; - TimeController* const time_controller_; + private: + absl::optional GetNextIPv4Address(); + const std::unique_ptr time_controller_; Clock* const clock_; int next_node_id_; diff --git a/test/network/network_emulation_pc_unittest.cc b/test/network/network_emulation_pc_unittest.cc index c1582263d8..e04da34076 100644 --- a/test/network/network_emulation_pc_unittest.cc +++ b/test/network/network_emulation_pc_unittest.cc @@ -99,7 +99,7 @@ TEST(NetworkEmulationManagerPCTest, Run) { signaling_thread->Start(); // Setup emulated network - NetworkEmulationManagerImpl emulation; + NetworkEmulationManagerImpl emulation(TimeMode::kRealTime); EmulatedNetworkNode* alice_node = emulation.CreateEmulatedNode( std::make_unique(BuiltInNetworkBehaviorConfig())); diff --git a/test/network/network_emulation_unittest.cc b/test/network/network_emulation_unittest.cc index 9a8a9823e2..70dfa77930 100644 --- a/test/network/network_emulation_unittest.cc +++ b/test/network/network_emulation_unittest.cc @@ -28,8 +28,8 @@ namespace webrtc { namespace test { namespace { -constexpr int kNetworkPacketWaitTimeoutMs = 100; -constexpr int kStatsWaitTimeoutMs = 1000; +constexpr TimeDelta kNetworkPacketWaitTimeout = TimeDelta::Millis<100>(); +constexpr TimeDelta kStatsWaitTimeout = TimeDelta::Seconds<1>(); constexpr int kOverheadIpv4Udp = 20 + 8; class SocketReader : public sigslot::has_slots<> { @@ -128,7 +128,7 @@ class NetworkEmulationManagerThreeNodesRoutingTest : public ::testing::Test { rtc::CopyOnWriteBuffer(10)); // Sleep at the end to wait for async packets delivery. - SleepMs(kNetworkPacketWaitTimeoutMs); + emulation_.time_controller()->AdvanceTime(kNetworkPacketWaitTimeout); } private: @@ -139,7 +139,7 @@ class NetworkEmulationManagerThreeNodesRoutingTest : public ::testing::Test { MockReceiver r_e1_e3_; MockReceiver r_e3_e1_; - NetworkEmulationManagerImpl emulation_; + NetworkEmulationManagerImpl emulation_{TimeMode::kRealTime}; EmulatedEndpoint* e1_; EmulatedEndpoint* e2_; EmulatedEndpoint* e3_; @@ -156,7 +156,7 @@ EmulatedNetworkNode* CreateEmulatedNodeWithDefaultBuiltInConfig( using ::testing::_; TEST(NetworkEmulationManagerTest, GeneratedIpv4AddressDoesNotCollide) { - NetworkEmulationManagerImpl network_manager; + NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime); std::set ips; EmulatedEndpointConfig config; config.generated_ip_family = EmulatedEndpointConfig::IpAddressFamily::kIpv4; @@ -169,7 +169,7 @@ TEST(NetworkEmulationManagerTest, GeneratedIpv4AddressDoesNotCollide) { } TEST(NetworkEmulationManagerTest, GeneratedIpv6AddressDoesNotCollide) { - NetworkEmulationManagerImpl network_manager; + NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime); std::set ips; EmulatedEndpointConfig config; config.generated_ip_family = EmulatedEndpointConfig::IpAddressFamily::kIpv6; @@ -182,7 +182,7 @@ TEST(NetworkEmulationManagerTest, GeneratedIpv6AddressDoesNotCollide) { } TEST(NetworkEmulationManagerTest, Run) { - NetworkEmulationManagerImpl network_manager; + NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime); EmulatedNetworkNode* alice_node = network_manager.CreateEmulatedNode( std::make_unique(BuiltInNetworkBehaviorConfig())); @@ -233,8 +233,8 @@ TEST(NetworkEmulationManagerTest, Run) { [&]() { s2->Send(data.data(), data.size()); }); } - rtc::Event wait; - wait.Wait(1000); + network_manager.time_controller()->AdvanceTime(TimeDelta::seconds(1)); + EXPECT_EQ(r1.ReceivedCount(), 1000); EXPECT_EQ(r2.ReceivedCount(), 1000); @@ -262,11 +262,13 @@ TEST(NetworkEmulationManagerTest, Run) { EXPECT_EQ(st.bytes_dropped.bytes(), 0l); received_stats_count++; }); - ASSERT_EQ_WAIT(received_stats_count.load(), 2, kStatsWaitTimeoutMs); + ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 2, + kStatsWaitTimeout.ms(), + *network_manager.time_controller()); } TEST(NetworkEmulationManagerTest, ThroughputStats) { - NetworkEmulationManagerImpl network_manager; + NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime); EmulatedNetworkNode* alice_node = network_manager.CreateEmulatedNode( std::make_unique(BuiltInNetworkBehaviorConfig())); @@ -313,12 +315,11 @@ TEST(NetworkEmulationManagerTest, ThroughputStats) { // Send 11 packets, totalizing 1 second between the first and the last. const int kNumPacketsSent = 11; - const int kDelayMs = 100; - rtc::Event wait; + const TimeDelta kDelay = TimeDelta::ms(100); for (int i = 0; i < kNumPacketsSent; i++) { t1->PostTask(RTC_FROM_HERE, [&]() { s1->Send(data.data(), data.size()); }); t2->PostTask(RTC_FROM_HERE, [&]() { s2->Send(data.data(), data.size()); }); - wait.Wait(kDelayMs); + network_manager.time_controller()->AdvanceTime(kDelay); } std::atomic received_stats_count{0}; @@ -328,11 +329,15 @@ TEST(NetworkEmulationManagerTest, ThroughputStats) { const double tolerance = 0.95; // Accept 5% tolerance for timing. EXPECT_GE(st.last_packet_sent_time - st.first_packet_sent_time, - TimeDelta::ms((kNumPacketsSent - 1) * kDelayMs * tolerance)); + (kNumPacketsSent - 1) * kDelay * tolerance); EXPECT_GT(st.AverageSendRate().bps(), 0); received_stats_count++; }); - ASSERT_EQ_WAIT(received_stats_count.load(), 1, kStatsWaitTimeoutMs); + + ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 1, + kStatsWaitTimeout.ms(), + *network_manager.time_controller()); + EXPECT_EQ(r1.ReceivedCount(), 11); EXPECT_EQ(r2.ReceivedCount(), 11); diff --git a/test/peer_scenario/peer_scenario.cc b/test/peer_scenario/peer_scenario.cc index 99d97c7190..c3443aa185 100644 --- a/test/peer_scenario/peer_scenario.cc +++ b/test/peer_scenario/peer_scenario.cc @@ -41,34 +41,22 @@ std::unique_ptr GetPeerScenarioLogManager( } return nullptr; } - -std::unique_ptr CreateTimeController(bool real_time) { - if (real_time) { - return std::make_unique(); - } else { - // Using an offset of 100000 to get nice fixed width and readable timestamps - // in typical test scenarios. - const Timestamp kSimulatedStartTime = Timestamp::seconds(100000); - return std::make_unique(kSimulatedStartTime); - } -} } // namespace -PeerScenario::PeerScenario(const testing::TestInfo& test_info, bool real_time) +PeerScenario::PeerScenario(const testing::TestInfo& test_info, TimeMode mode) : PeerScenario( std::string(test_info.test_suite_name()) + "/" + test_info.name(), - real_time) {} + mode) {} -PeerScenario::PeerScenario(std::string file_name, bool real_time) - : PeerScenario(GetPeerScenarioLogManager(file_name), real_time) {} +PeerScenario::PeerScenario(std::string file_name, TimeMode mode) + : PeerScenario(GetPeerScenarioLogManager(file_name), mode) {} PeerScenario::PeerScenario( std::unique_ptr log_writer_manager, - bool real_time) + TimeMode mode) : log_writer_manager_(std::move(log_writer_manager)), - time_controller_(CreateTimeController(real_time)), - signaling_thread_(time_controller_->GetMainThread()), - net_(time_controller_.get()) {} + net_(mode), + signaling_thread_(net_.time_controller()->GetMainThread()) {} PeerScenarioClient* PeerScenario::CreateClient( PeerScenarioClient::Config config) { @@ -79,7 +67,7 @@ PeerScenarioClient* PeerScenario::CreateClient( PeerScenarioClient* PeerScenario::CreateClient( std::string name, PeerScenarioClient::Config config) { - peer_clients_.emplace_back(net(), time_controller_.get(), thread(), + peer_clients_.emplace_back(net(), signaling_thread_, GetLogWriterFactory(name), config); return &peer_clients_.back(); } @@ -119,20 +107,12 @@ void PeerScenario::AttachVideoQualityAnalyzer(VideoQualityAnalyzer* analyzer, bool PeerScenario::WaitAndProcess(std::atomic* event, TimeDelta max_duration) { - const auto kStep = TimeDelta::ms(5); - if (*event) - return true; - for (auto elapsed = TimeDelta::Zero(); elapsed < max_duration; - elapsed += kStep) { - time_controller_->AdvanceTime(kStep); - if (*event) - return true; - } - return false; + return net_.time_controller()->Wait([event] { return event->load(); }, + max_duration); } void PeerScenario::ProcessMessages(TimeDelta duration) { - time_controller_->AdvanceTime(duration); + net_.time_controller()->AdvanceTime(duration); } std::unique_ptr PeerScenario::GetLogWriterFactory( diff --git a/test/peer_scenario/peer_scenario.h b/test/peer_scenario/peer_scenario.h index 94dd4425b9..8d6ad1b00c 100644 --- a/test/peer_scenario/peer_scenario.h +++ b/test/peer_scenario/peer_scenario.h @@ -47,14 +47,14 @@ class PeerScenario { // command line flag. Optionally, the TestInfo struct available in gtest can // be used to automatically generate a path based on the test name. explicit PeerScenario(const testing::TestInfo& test_info, - bool real_time = false); - explicit PeerScenario(std::string file_name, bool real_time = false); + TimeMode mode = TimeMode::kSimulated); + explicit PeerScenario(std::string file_name, + TimeMode mode = TimeMode::kSimulated); explicit PeerScenario( std::unique_ptr log_writer_manager, - bool real_time = false); + TimeMode mode = TimeMode::kSimulated); NetworkEmulationManagerImpl* net() { return &net_; } - rtc::Thread* thread() { return signaling_thread_; } // Creates a client wrapping a peer connection conforming to the given config. // The client will share the signaling thread with the scenario. To maintain @@ -111,10 +111,9 @@ class PeerScenario { std::string name); const std::unique_ptr log_writer_manager_; - const std::unique_ptr time_controller_; + NetworkEmulationManagerImpl net_; rtc::Thread* const signaling_thread_; std::list video_quality_pairs_; - NetworkEmulationManagerImpl net_; std::list peer_clients_; }; diff --git a/test/peer_scenario/peer_scenario_client.cc b/test/peer_scenario/peer_scenario_client.cc index 0ee709e60e..4614942f78 100644 --- a/test/peer_scenario/peer_scenario_client.cc +++ b/test/peer_scenario/peer_scenario_client.cc @@ -147,15 +147,14 @@ class TimeControllerBasedCallFactory : public CallFactoryInterface { PeerScenarioClient::PeerScenarioClient( NetworkEmulationManager* net, - TimeController* time_controller, rtc::Thread* signaling_thread, std::unique_ptr log_writer_factory, PeerScenarioClient::Config config) : endpoints_(CreateEndpoints(net, config.endpoints)), - task_queue_factory_(time_controller->GetTaskQueueFactory()), + task_queue_factory_(net->time_controller()->GetTaskQueueFactory()), signaling_thread_(signaling_thread), log_writer_factory_(std::move(log_writer_factory)), - worker_thread_(time_controller->CreateThread("worker")), + worker_thread_(net->time_controller()->CreateThread("worker")), handlers_(config.handlers), observer_(new LambdaPeerConnectionObserver(&handlers_)) { handlers_.on_track.push_back( @@ -191,7 +190,7 @@ PeerScenarioClient::PeerScenarioClient( pcf_deps.signaling_thread = signaling_thread_; pcf_deps.worker_thread = worker_thread_.get(); pcf_deps.call_factory = - std::make_unique(time_controller); + std::make_unique(net->time_controller()); pcf_deps.task_queue_factory = std::make_unique(task_queue_factory_); pcf_deps.event_log_factory = diff --git a/test/peer_scenario/peer_scenario_client.h b/test/peer_scenario/peer_scenario_client.h index e9b86e2bf3..b832f903e6 100644 --- a/test/peer_scenario/peer_scenario_client.h +++ b/test/peer_scenario/peer_scenario_client.h @@ -108,7 +108,6 @@ class PeerScenarioClient { PeerScenarioClient( NetworkEmulationManager* net, - TimeController* time_controller, rtc::Thread* signaling_thread, std::unique_ptr log_writer_factory, Config config); diff --git a/test/scenario/scenario.cc b/test/scenario/scenario.cc index 0c5e3814fd..e4e4f8d2d0 100644 --- a/test/scenario/scenario.cc +++ b/test/scenario/scenario.cc @@ -20,8 +20,6 @@ #include "test/logging/file_log_writer.h" #include "test/network/network_emulation.h" #include "test/testsupport/file_utils.h" -#include "test/time_controller/real_time_controller.h" -#include "test/time_controller/simulated_time_controller.h" ABSL_FLAG(bool, scenario_logs, false, "Save logs from scenario framework."); ABSL_FLAG(std::string, @@ -47,13 +45,6 @@ std::unique_ptr GetScenarioLogManager( } return nullptr; } -std::unique_ptr CreateTimeController(bool real_time) { - if (real_time) { - return std::make_unique(); - } else { - return std::make_unique(kSimulatedStartTime); - } -} } // namespace Scenario::Scenario() @@ -74,14 +65,14 @@ Scenario::Scenario( std::unique_ptr log_writer_factory, bool real_time) : log_writer_factory_(std::move(log_writer_factory)), - time_controller_(CreateTimeController(real_time)), - network_manager_(time_controller_.get()), - clock_(time_controller_->GetClock()), + network_manager_(real_time ? TimeMode::kRealTime : TimeMode::kSimulated), + clock_(network_manager_.time_controller()->GetClock()), audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()), audio_encoder_factory_(CreateBuiltinAudioEncoderFactory()), - task_queue_(time_controller_->GetTaskQueueFactory()->CreateTaskQueue( - "Scenario", - TaskQueueFactory::Priority::NORMAL)) {} + task_queue_(network_manager_.time_controller() + ->GetTaskQueueFactory() + ->CreateTaskQueue("Scenario", + TaskQueueFactory::Priority::NORMAL)) {} Scenario::~Scenario() { if (start_time_.IsFinite()) @@ -116,8 +107,8 @@ StatesPrinter* Scenario::CreatePrinter(std::string name, } CallClient* Scenario::CreateClient(std::string name, CallClientConfig config) { - CallClient* client = - new CallClient(time_controller_.get(), GetLogWriterFactory(name), config); + CallClient* client = new CallClient(network_manager_.time_controller(), + GetLogWriterFactory(name), config); if (config.transport.state_log_interval.IsFinite()) { Every(config.transport.state_log_interval, [this, client]() { client->network_controller_factory_.LogCongestionControllerStats(Now()); @@ -282,7 +273,7 @@ void Scenario::At(TimeDelta offset, std::function function) { void Scenario::RunFor(TimeDelta duration) { if (start_time_.IsInfinite()) Start(); - time_controller_->AdvanceTime(duration); + network_manager_.time_controller()->AdvanceTime(duration); } void Scenario::RunUntil(TimeDelta target_time_since_start) { @@ -295,11 +286,12 @@ void Scenario::RunUntil(TimeDelta target_time_since_start, if (start_time_.IsInfinite()) Start(); while (check_interval >= TimeUntilTarget(target_time_since_start)) { - time_controller_->AdvanceTime(check_interval); + network_manager_.time_controller()->AdvanceTime(check_interval); if (exit_function()) return; } - time_controller_->AdvanceTime(TimeUntilTarget(target_time_since_start)); + network_manager_.time_controller()->AdvanceTime( + TimeUntilTarget(target_time_since_start)); } void Scenario::Start() { diff --git a/test/scenario/scenario.h b/test/scenario/scenario.h index a5803bf60d..1aad5b9cd1 100644 --- a/test/scenario/scenario.h +++ b/test/scenario/scenario.h @@ -161,7 +161,6 @@ class Scenario { TimeDelta TimeUntilTarget(TimeDelta target_time_offset); const std::unique_ptr log_writer_factory_; - std::unique_ptr time_controller_; NetworkEmulationManagerImpl network_manager_; Clock* clock_; diff --git a/test/time_controller/real_time_controller.cc b/test/time_controller/real_time_controller.cc index d9fd9dcb51..73772b968f 100644 --- a/test/time_controller/real_time_controller.cc +++ b/test/time_controller/real_time_controller.cc @@ -14,8 +14,28 @@ #include "system_wrappers/include/sleep.h" namespace webrtc { +namespace { +class MainThread : public rtc::Thread { + public: + MainThread() + : Thread(std::make_unique(), false), + current_setter_(this) { + DoInit(); + } + ~MainThread() { + Stop(); + DoDestroy(); + } + + private: + CurrentThreadSetter current_setter_; +}; +} // namespace RealTimeController::RealTimeController() - : task_queue_factory_(CreateDefaultTaskQueueFactory()) {} + : task_queue_factory_(CreateDefaultTaskQueueFactory()), + main_thread_(std::make_unique()) { + main_thread_->SetName("Main", this); +} Clock* RealTimeController::GetClock() { return Clock::GetRealTimeClock(); @@ -42,16 +62,11 @@ std::unique_ptr RealTimeController::CreateThread( } rtc::Thread* RealTimeController::GetMainThread() { - return rtc::Thread::Current(); + return main_thread_.get(); } void RealTimeController::AdvanceTime(TimeDelta duration) { - GetMainThread()->ProcessMessages(duration.ms()); -} - -RealTimeController* GlobalRealTimeController() { - static RealTimeController* time_controller = new RealTimeController(); - return time_controller; + main_thread_->ProcessMessages(duration.ms()); } } // namespace webrtc diff --git a/test/time_controller/real_time_controller.h b/test/time_controller/real_time_controller.h index f68fe441d5..bbee6ef967 100644 --- a/test/time_controller/real_time_controller.h +++ b/test/time_controller/real_time_controller.h @@ -36,10 +36,9 @@ class RealTimeController : public TimeController { private: const std::unique_ptr task_queue_factory_; + const std::unique_ptr main_thread_; }; -RealTimeController* GlobalRealTimeController(); - } // namespace webrtc #endif // TEST_TIME_CONTROLLER_REAL_TIME_CONTROLLER_H_ diff --git a/test/time_controller/simulated_thread.h b/test/time_controller/simulated_thread.h index bbaafd75bd..fd3969670a 100644 --- a/test/time_controller/simulated_thread.h +++ b/test/time_controller/simulated_thread.h @@ -19,20 +19,7 @@ namespace webrtc { class SimulatedThread : public rtc::Thread, public sim_time_impl::SimulatedSequenceRunner { public: - class CurrentThreadSetter : CurrentTaskQueueSetter { - public: - explicit CurrentThreadSetter(Thread* thread) - : CurrentTaskQueueSetter(thread), - manager_(rtc::ThreadManager::Instance()), - previous_(manager_->CurrentThread()) { - manager_->ChangeCurrentThreadForTest(thread); - } - ~CurrentThreadSetter() { manager_->ChangeCurrentThreadForTest(previous_); } - - private: - rtc::ThreadManager* const manager_; - rtc::Thread* const previous_; - }; + using CurrentThreadSetter = CurrentThreadSetter; SimulatedThread(sim_time_impl::SimulatedTimeControllerImpl* handler, absl::string_view name, std::unique_ptr socket_server);