blob: 134cf08118c49da2a5861146c3f6f79b705e8268 [file] [log] [blame]
Sebastian Jansson98b07e92018-09-27 13:47:01 +02001/*
2 * Copyright 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10#ifndef TEST_SCENARIO_SCENARIO_H_
11#define TEST_SCENARIO_SCENARIO_H_
12#include <memory>
13#include <string>
14#include <utility>
15#include <vector>
16
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080017#include "api/test/time_controller.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "rtc_base/constructor_magic.h"
19#include "rtc_base/fake_clock.h"
Sebastian Jansson105a10a2019-04-01 09:18:14 +020020#include "rtc_base/task_queue.h"
21#include "rtc_base/task_utils/repeating_task.h"
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +010022#include "test/gtest.h"
Sebastian Jansson52de8b02019-01-16 17:25:44 +010023#include "test/logging/log_writer.h"
Artem Titov386802e2019-07-05 10:48:17 +020024#include "test/network/network_emulation_manager.h"
Sebastian Jansson98b07e92018-09-27 13:47:01 +020025#include "test/scenario/audio_stream.h"
26#include "test/scenario/call_client.h"
27#include "test/scenario/column_printer.h"
28#include "test/scenario/network_node.h"
29#include "test/scenario/scenario_config.h"
30#include "test/scenario/video_stream.h"
31
32namespace webrtc {
33namespace test {
Sebastian Jansson98b07e92018-09-27 13:47:01 +020034// Scenario is a class owning everything for a test scenario. It creates and
35// holds network nodes, call clients and media streams. It also provides methods
36// for changing behavior at runtime. Since it always keeps ownership of the
37// created components, it generally returns non-owning pointers. It maintains
38// the life of its objects until it is destroyed.
39// For methods accepting configuration structs, a modifier function interface is
40// generally provided. This allows simple partial overriding of the default
41// configuration.
42class Scenario {
43 public:
44 Scenario();
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +010045 explicit Scenario(const testing::TestInfo* test_info);
Sebastian Jansson98b07e92018-09-27 13:47:01 +020046 explicit Scenario(std::string file_name);
47 Scenario(std::string file_name, bool real_time);
Sebastian Jansson52de8b02019-01-16 17:25:44 +010048 Scenario(std::unique_ptr<LogWriterFactoryInterface> log_writer_manager,
49 bool real_time);
Sebastian Jansson98b07e92018-09-27 13:47:01 +020050 RTC_DISALLOW_COPY_AND_ASSIGN(Scenario);
51 ~Scenario();
Sebastian Janssona4c22b92019-04-15 21:10:00 +020052 NetworkEmulationManagerImpl* net() { return &network_manager_; }
Sebastian Jansson98b07e92018-09-27 13:47:01 +020053
Sebastian Janssonef86d142019-04-15 14:42:42 +020054 EmulatedNetworkNode* CreateSimulationNode(NetworkSimulationConfig config);
55 EmulatedNetworkNode* CreateSimulationNode(
56 std::function<void(NetworkSimulationConfig*)> config_modifier);
57
58 SimulationNode* CreateMutableSimulationNode(NetworkSimulationConfig config);
59 SimulationNode* CreateMutableSimulationNode(
60 std::function<void(NetworkSimulationConfig*)> config_modifier);
Sebastian Jansson98b07e92018-09-27 13:47:01 +020061
62 CallClient* CreateClient(std::string name, CallClientConfig config);
63 CallClient* CreateClient(
64 std::string name,
65 std::function<void(CallClientConfig*)> config_modifier);
66
Sebastian Jansson800e1212018-10-22 11:49:03 +020067 CallClientPair* CreateRoutes(CallClient* first,
Artem Titov37d18482019-01-08 15:41:45 +010068 std::vector<EmulatedNetworkNode*> send_link,
Sebastian Jansson800e1212018-10-22 11:49:03 +020069 CallClient* second,
Artem Titov37d18482019-01-08 15:41:45 +010070 std::vector<EmulatedNetworkNode*> return_link);
Sebastian Jansson800e1212018-10-22 11:49:03 +020071
72 CallClientPair* CreateRoutes(CallClient* first,
Artem Titov37d18482019-01-08 15:41:45 +010073 std::vector<EmulatedNetworkNode*> send_link,
Sebastian Jansson800e1212018-10-22 11:49:03 +020074 DataSize first_overhead,
75 CallClient* second,
Artem Titov37d18482019-01-08 15:41:45 +010076 std::vector<EmulatedNetworkNode*> return_link,
Sebastian Jansson800e1212018-10-22 11:49:03 +020077 DataSize second_overhead);
78
79 void ChangeRoute(std::pair<CallClient*, CallClient*> clients,
Artem Titov37d18482019-01-08 15:41:45 +010080 std::vector<EmulatedNetworkNode*> over_nodes);
Sebastian Jansson800e1212018-10-22 11:49:03 +020081
82 void ChangeRoute(std::pair<CallClient*, CallClient*> clients,
Artem Titov37d18482019-01-08 15:41:45 +010083 std::vector<EmulatedNetworkNode*> over_nodes,
Sebastian Jansson800e1212018-10-22 11:49:03 +020084 DataSize overhead);
85
Sebastian Jansson98b07e92018-09-27 13:47:01 +020086 VideoStreamPair* CreateVideoStream(
Sebastian Jansson800e1212018-10-22 11:49:03 +020087 std::pair<CallClient*, CallClient*> clients,
Sebastian Jansson98b07e92018-09-27 13:47:01 +020088 std::function<void(VideoStreamConfig*)> config_modifier);
Sebastian Jansson800e1212018-10-22 11:49:03 +020089 VideoStreamPair* CreateVideoStream(
90 std::pair<CallClient*, CallClient*> clients,
91 VideoStreamConfig config);
Sebastian Jansson98b07e92018-09-27 13:47:01 +020092
93 AudioStreamPair* CreateAudioStream(
Sebastian Jansson800e1212018-10-22 11:49:03 +020094 std::pair<CallClient*, CallClient*> clients,
Sebastian Jansson98b07e92018-09-27 13:47:01 +020095 std::function<void(AudioStreamConfig*)> config_modifier);
Sebastian Jansson800e1212018-10-22 11:49:03 +020096 AudioStreamPair* CreateAudioStream(
97 std::pair<CallClient*, CallClient*> clients,
98 AudioStreamConfig config);
Sebastian Jansson98b07e92018-09-27 13:47:01 +020099
Sebastian Jansson105a10a2019-04-01 09:18:14 +0200100 // Runs the provided function with a fixed interval. For real time tests,
Artem Titov1ee563d2021-07-27 12:46:29 +0200101 // `function` starts being called after `interval` from the call to Every().
Sebastian Jansson123f3452019-03-13 11:22:52 +0100102 void Every(TimeDelta interval, std::function<void(TimeDelta)> function);
103 void Every(TimeDelta interval, std::function<void()> function);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200104
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100105 // Runs the provided function on the internal task queue. This ensure that
106 // it's run on the main thread for simulated time tests.
107 void Post(std::function<void()> function);
108
Sebastian Jansson105a10a2019-04-01 09:18:14 +0200109 // Runs the provided function after given duration has passed. For real time
Artem Titov1ee563d2021-07-27 12:46:29 +0200110 // tests, `function` is called after `target_time_since_start` from the call
Sebastian Jansson105a10a2019-04-01 09:18:14 +0200111 // to Every().
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200112 void At(TimeDelta offset, std::function<void()> function);
113
Artem Titov1ee563d2021-07-27 12:46:29 +0200114 // Sends a packet over the nodes and runs `action` when it has been delivered.
Artem Titov37d18482019-01-08 15:41:45 +0100115 void NetworkDelayedAction(std::vector<EmulatedNetworkNode*> over_nodes,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200116 size_t packet_size,
117 std::function<void()> action);
118
Sebastian Jansson105a10a2019-04-01 09:18:14 +0200119 // Runs the scenario for the given time.
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200120 void RunFor(TimeDelta duration);
Artem Titov1ee563d2021-07-27 12:46:29 +0200121 // Runs the scenario until `target_time_since_start`.
Sebastian Jansson123f3452019-03-13 11:22:52 +0100122 void RunUntil(TimeDelta target_time_since_start);
Artem Titov1ee563d2021-07-27 12:46:29 +0200123 // Runs the scenario until `target_time_since_start` or `exit_function`
124 // returns true. `exit_function` is polled after each `check_interval` has
Sebastian Jansson105a10a2019-04-01 09:18:14 +0200125 // passed.
Sebastian Jansson123f3452019-03-13 11:22:52 +0100126 void RunUntil(TimeDelta target_time_since_start,
127 TimeDelta check_interval,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200128 std::function<bool()> exit_function);
Sebastian Jansson49a78432018-11-20 16:15:29 +0100129 void Start();
130 void Stop();
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200131
132 // Triggers sending of dummy packets over the given nodes.
Artem Titov37d18482019-01-08 15:41:45 +0100133 void TriggerPacketBurst(std::vector<EmulatedNetworkNode*> over_nodes,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200134 size_t num_packets,
135 size_t packet_size);
136
137 ColumnPrinter TimePrinter();
138 StatesPrinter* CreatePrinter(std::string name,
139 TimeDelta interval,
140 std::vector<ColumnPrinter> printers);
141
142 // Returns the current time.
143 Timestamp Now();
144 // Return the duration of the current session so far.
Sebastian Jansson123f3452019-03-13 11:22:52 +0100145 TimeDelta TimeSinceStart();
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200146
Sebastian Jansson52de8b02019-01-16 17:25:44 +0100147 std::unique_ptr<RtcEventLogOutput> GetLogWriter(std::string name) {
148 if (!log_writer_factory_ || name.empty())
149 return nullptr;
150 return log_writer_factory_->Create(name);
151 }
152 std::unique_ptr<LogWriterFactoryInterface> GetLogWriterFactory(
153 std::string name) {
154 if (!log_writer_factory_ || name.empty())
155 return nullptr;
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200156 return std::make_unique<LogWriterFactoryAddPrefix>(
Sebastian Jansson52de8b02019-01-16 17:25:44 +0100157 log_writer_factory_.get(), name);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200158 }
159
160 private:
Sebastian Jansson105a10a2019-04-01 09:18:14 +0200161 TimeDelta TimeUntilTarget(TimeDelta target_time_offset);
162
Sebastian Jansson105a10a2019-04-01 09:18:14 +0200163 const std::unique_ptr<LogWriterFactoryInterface> log_writer_factory_;
Sebastian Jansson77bd3852020-01-17 13:05:54 +0100164 NetworkEmulationManagerImpl network_manager_;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200165 Clock* clock_;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200166
167 std::vector<std::unique_ptr<CallClient>> clients_;
Sebastian Jansson800e1212018-10-22 11:49:03 +0200168 std::vector<std::unique_ptr<CallClientPair>> client_pairs_;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200169 std::vector<std::unique_ptr<VideoStreamPair>> video_streams_;
170 std::vector<std::unique_ptr<AudioStreamPair>> audio_streams_;
Sebastian Janssona4c22b92019-04-15 21:10:00 +0200171 std::vector<std::unique_ptr<SimulationNode>> simulation_nodes_;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200172 std::vector<std::unique_ptr<StatesPrinter>> printers_;
173
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200174 rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory_;
175 rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory_;
176
177 Timestamp start_time_ = Timestamp::PlusInfinity();
Sebastian Jansson105a10a2019-04-01 09:18:14 +0200178 // Defined last so it's destroyed first.
179 rtc::TaskQueue task_queue_;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200180};
181} // namespace test
182} // namespace webrtc
183
184#endif // TEST_SCENARIO_SCENARIO_H_