/* * Copyright 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. */ #ifndef TEST_SCENARIO_SCENARIO_H_ #define TEST_SCENARIO_SCENARIO_H_ #include <memory> #include <string> #include <utility> #include <vector> #include "api/test/time_controller.h" #include "rtc_base/constructor_magic.h" #include "rtc_base/fake_clock.h" #include "rtc_base/task_queue.h" #include "rtc_base/task_utils/repeating_task.h" #include "test/gtest.h" #include "test/logging/log_writer.h" #include "test/network/network_emulation_manager.h" #include "test/scenario/audio_stream.h" #include "test/scenario/call_client.h" #include "test/scenario/column_printer.h" #include "test/scenario/network_node.h" #include "test/scenario/scenario_config.h" #include "test/scenario/video_stream.h" namespace webrtc { namespace test { // Scenario is a class owning everything for a test scenario. It creates and // holds network nodes, call clients and media streams. It also provides methods // for changing behavior at runtime. Since it always keeps ownership of the // created components, it generally returns non-owning pointers. It maintains // the life of its objects until it is destroyed. // For methods accepting configuration structs, a modifier function interface is // generally provided. This allows simple partial overriding of the default // configuration. class Scenario { public: Scenario(); explicit Scenario(const testing::TestInfo* test_info); explicit Scenario(std::string file_name); Scenario(std::string file_name, bool real_time); Scenario(std::unique_ptr<LogWriterFactoryInterface> log_writer_manager, bool real_time); RTC_DISALLOW_COPY_AND_ASSIGN(Scenario); ~Scenario(); NetworkEmulationManagerImpl* net() { return &network_manager_; } EmulatedNetworkNode* CreateSimulationNode(NetworkSimulationConfig config); EmulatedNetworkNode* CreateSimulationNode( std::function<void(NetworkSimulationConfig*)> config_modifier); SimulationNode* CreateMutableSimulationNode(NetworkSimulationConfig config); SimulationNode* CreateMutableSimulationNode( std::function<void(NetworkSimulationConfig*)> config_modifier); CallClient* CreateClient(std::string name, CallClientConfig config); CallClient* CreateClient( std::string name, std::function<void(CallClientConfig*)> config_modifier); CallClientPair* CreateRoutes(CallClient* first, std::vector<EmulatedNetworkNode*> send_link, CallClient* second, std::vector<EmulatedNetworkNode*> return_link); CallClientPair* CreateRoutes(CallClient* first, std::vector<EmulatedNetworkNode*> send_link, DataSize first_overhead, CallClient* second, std::vector<EmulatedNetworkNode*> return_link, DataSize second_overhead); void ChangeRoute(std::pair<CallClient*, CallClient*> clients, std::vector<EmulatedNetworkNode*> over_nodes); void ChangeRoute(std::pair<CallClient*, CallClient*> clients, std::vector<EmulatedNetworkNode*> over_nodes, DataSize overhead); VideoStreamPair* CreateVideoStream( std::pair<CallClient*, CallClient*> clients, std::function<void(VideoStreamConfig*)> config_modifier); VideoStreamPair* CreateVideoStream( std::pair<CallClient*, CallClient*> clients, VideoStreamConfig config); AudioStreamPair* CreateAudioStream( std::pair<CallClient*, CallClient*> clients, std::function<void(AudioStreamConfig*)> config_modifier); AudioStreamPair* CreateAudioStream( std::pair<CallClient*, CallClient*> clients, AudioStreamConfig config); // Runs the provided function with a fixed interval. For real time tests, // |function| starts being called after |interval| from the call to Every(). void Every(TimeDelta interval, std::function<void(TimeDelta)> function); void Every(TimeDelta interval, std::function<void()> function); // Runs the provided function on the internal task queue. This ensure that // it's run on the main thread for simulated time tests. void Post(std::function<void()> function); // Runs the provided function after given duration has passed. For real time // tests, |function| is called after |target_time_since_start| from the call // to Every(). void At(TimeDelta offset, std::function<void()> function); // Sends a packet over the nodes and runs |action| when it has been delivered. void NetworkDelayedAction(std::vector<EmulatedNetworkNode*> over_nodes, size_t packet_size, std::function<void()> action); // Runs the scenario for the given time. void RunFor(TimeDelta duration); // Runs the scenario until |target_time_since_start|. void RunUntil(TimeDelta target_time_since_start); // Runs the scenario until |target_time_since_start| or |exit_function| // returns true. |exit_function| is polled after each |check_interval| has // passed. void RunUntil(TimeDelta target_time_since_start, TimeDelta check_interval, std::function<bool()> exit_function); void Start(); void Stop(); // Triggers sending of dummy packets over the given nodes. void TriggerPacketBurst(std::vector<EmulatedNetworkNode*> over_nodes, size_t num_packets, size_t packet_size); ColumnPrinter TimePrinter(); StatesPrinter* CreatePrinter(std::string name, TimeDelta interval, std::vector<ColumnPrinter> printers); // Returns the current time. Timestamp Now(); // Return the duration of the current session so far. TimeDelta TimeSinceStart(); std::unique_ptr<RtcEventLogOutput> GetLogWriter(std::string name) { if (!log_writer_factory_ || name.empty()) return nullptr; return log_writer_factory_->Create(name); } std::unique_ptr<LogWriterFactoryInterface> GetLogWriterFactory( std::string name) { if (!log_writer_factory_ || name.empty()) return nullptr; return std::make_unique<LogWriterFactoryAddPrefix>( log_writer_factory_.get(), name); } private: TimeDelta TimeUntilTarget(TimeDelta target_time_offset); const std::unique_ptr<LogWriterFactoryInterface> log_writer_factory_; NetworkEmulationManagerImpl network_manager_; Clock* clock_; std::vector<std::unique_ptr<CallClient>> clients_; std::vector<std::unique_ptr<CallClientPair>> client_pairs_; std::vector<std::unique_ptr<VideoStreamPair>> video_streams_; std::vector<std::unique_ptr<AudioStreamPair>> audio_streams_; std::vector<std::unique_ptr<SimulationNode>> simulation_nodes_; std::vector<std::unique_ptr<StatesPrinter>> printers_; rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory_; rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory_; Timestamp start_time_ = Timestamp::PlusInfinity(); // Defined last so it's destroyed first. rtc::TaskQueue task_queue_; }; } // namespace test } // namespace webrtc #endif // TEST_SCENARIO_SCENARIO_H_