blob: 6de1d78f7d8fb27f9b87ad51556f9e03d6f8085f [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
Sebastian Jansson52de8b02019-01-16 17:25:44 +010017#include "absl/memory/memory.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "rtc_base/constructor_magic.h"
19#include "rtc_base/fake_clock.h"
Sebastian Jansson52de8b02019-01-16 17:25:44 +010020#include "test/logging/log_writer.h"
Sebastian Jansson98b07e92018-09-27 13:47:01 +020021#include "test/scenario/audio_stream.h"
22#include "test/scenario/call_client.h"
23#include "test/scenario/column_printer.h"
24#include "test/scenario/network_node.h"
25#include "test/scenario/scenario_config.h"
Sebastian Jansson71a091e2018-09-27 19:08:21 +020026#include "test/scenario/simulated_time.h"
Sebastian Jansson98b07e92018-09-27 13:47:01 +020027#include "test/scenario/video_stream.h"
28
29namespace webrtc {
30namespace test {
31// RepeatedActivity is created by the Scenario class and can be used to stop a
32// running activity at runtime.
33class RepeatedActivity {
34 public:
35 void Stop();
36
37 private:
38 friend class Scenario;
39 RepeatedActivity(TimeDelta interval, std::function<void(TimeDelta)> function);
40
41 void Poll(Timestamp time);
42 void SetStartTime(Timestamp time);
43 Timestamp NextTime();
44
45 TimeDelta interval_;
46 std::function<void(TimeDelta)> function_;
47 Timestamp last_update_ = Timestamp::MinusInfinity();
48};
49
50struct PendingActivity {
51 TimeDelta after_duration;
52 std::function<void()> function;
53};
54
55// Scenario is a class owning everything for a test scenario. It creates and
56// holds network nodes, call clients and media streams. It also provides methods
57// for changing behavior at runtime. Since it always keeps ownership of the
58// created components, it generally returns non-owning pointers. It maintains
59// the life of its objects until it is destroyed.
60// For methods accepting configuration structs, a modifier function interface is
61// generally provided. This allows simple partial overriding of the default
62// configuration.
63class Scenario {
64 public:
65 Scenario();
66 explicit Scenario(std::string file_name);
67 Scenario(std::string file_name, bool real_time);
Sebastian Jansson52de8b02019-01-16 17:25:44 +010068 Scenario(std::unique_ptr<LogWriterFactoryInterface> log_writer_manager,
69 bool real_time);
Sebastian Jansson98b07e92018-09-27 13:47:01 +020070 RTC_DISALLOW_COPY_AND_ASSIGN(Scenario);
71 ~Scenario();
72
73 SimulationNode* CreateSimulationNode(NetworkNodeConfig config);
74 SimulationNode* CreateSimulationNode(
75 std::function<void(NetworkNodeConfig*)> config_modifier);
Artem Titov37d18482019-01-08 15:41:45 +010076 EmulatedNetworkNode* CreateNetworkNode(
Artem Titov8ea1e9d2018-10-04 14:46:31 +020077 std::unique_ptr<NetworkBehaviorInterface> behavior);
Sebastian Jansson98b07e92018-09-27 13:47:01 +020078
79 CallClient* CreateClient(std::string name, CallClientConfig config);
80 CallClient* CreateClient(
81 std::string name,
82 std::function<void(CallClientConfig*)> config_modifier);
83
Sebastian Jansson800e1212018-10-22 11:49:03 +020084 CallClientPair* CreateRoutes(CallClient* first,
Artem Titov37d18482019-01-08 15:41:45 +010085 std::vector<EmulatedNetworkNode*> send_link,
Sebastian Jansson800e1212018-10-22 11:49:03 +020086 CallClient* second,
Artem Titov37d18482019-01-08 15:41:45 +010087 std::vector<EmulatedNetworkNode*> return_link);
Sebastian Jansson800e1212018-10-22 11:49:03 +020088
89 CallClientPair* CreateRoutes(CallClient* first,
Artem Titov37d18482019-01-08 15:41:45 +010090 std::vector<EmulatedNetworkNode*> send_link,
Sebastian Jansson800e1212018-10-22 11:49:03 +020091 DataSize first_overhead,
92 CallClient* second,
Artem Titov37d18482019-01-08 15:41:45 +010093 std::vector<EmulatedNetworkNode*> return_link,
Sebastian Jansson800e1212018-10-22 11:49:03 +020094 DataSize second_overhead);
95
96 void ChangeRoute(std::pair<CallClient*, CallClient*> clients,
Artem Titov37d18482019-01-08 15:41:45 +010097 std::vector<EmulatedNetworkNode*> over_nodes);
Sebastian Jansson800e1212018-10-22 11:49:03 +020098
99 void ChangeRoute(std::pair<CallClient*, CallClient*> clients,
Artem Titov37d18482019-01-08 15:41:45 +0100100 std::vector<EmulatedNetworkNode*> over_nodes,
Sebastian Jansson800e1212018-10-22 11:49:03 +0200101 DataSize overhead);
102
Sebastian Jansson71a091e2018-09-27 19:08:21 +0200103 SimulatedTimeClient* CreateSimulatedTimeClient(
104 std::string name,
105 SimulatedTimeClientConfig config,
106 std::vector<PacketStreamConfig> stream_configs,
Artem Titov37d18482019-01-08 15:41:45 +0100107 std::vector<EmulatedNetworkNode*> send_link,
108 std::vector<EmulatedNetworkNode*> return_link);
Sebastian Jansson71a091e2018-09-27 19:08:21 +0200109
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200110 VideoStreamPair* CreateVideoStream(
Sebastian Jansson800e1212018-10-22 11:49:03 +0200111 std::pair<CallClient*, CallClient*> clients,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200112 std::function<void(VideoStreamConfig*)> config_modifier);
Sebastian Jansson800e1212018-10-22 11:49:03 +0200113 VideoStreamPair* CreateVideoStream(
114 std::pair<CallClient*, CallClient*> clients,
115 VideoStreamConfig config);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200116
117 AudioStreamPair* CreateAudioStream(
Sebastian Jansson800e1212018-10-22 11:49:03 +0200118 std::pair<CallClient*, CallClient*> clients,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200119 std::function<void(AudioStreamConfig*)> config_modifier);
Sebastian Jansson800e1212018-10-22 11:49:03 +0200120 AudioStreamPair* CreateAudioStream(
121 std::pair<CallClient*, CallClient*> clients,
122 AudioStreamConfig config);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200123
124 CrossTrafficSource* CreateCrossTraffic(
Artem Titov37d18482019-01-08 15:41:45 +0100125 std::vector<EmulatedNetworkNode*> over_nodes,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200126 std::function<void(CrossTrafficConfig*)> config_modifier);
Artem Titov37d18482019-01-08 15:41:45 +0100127 CrossTrafficSource* CreateCrossTraffic(
128 std::vector<EmulatedNetworkNode*> over_nodes,
129 CrossTrafficConfig config);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200130
131 // Runs the provided function with a fixed interval.
Sebastian Jansson123f3452019-03-13 11:22:52 +0100132 void Every(TimeDelta interval, std::function<void(TimeDelta)> function);
133 void Every(TimeDelta interval, std::function<void()> function);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200134
135 // Runs the provided function after given duration has passed in a session.
136 void At(TimeDelta offset, std::function<void()> function);
137
138 // Sends a packet over the nodes and runs |action| when it has been delivered.
Artem Titov37d18482019-01-08 15:41:45 +0100139 void NetworkDelayedAction(std::vector<EmulatedNetworkNode*> over_nodes,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200140 size_t packet_size,
141 std::function<void()> action);
142
143 // Runs the scenario for the given time or until the exit function returns
144 // true.
145 void RunFor(TimeDelta duration);
Sebastian Jansson123f3452019-03-13 11:22:52 +0100146 void RunUntil(TimeDelta target_time_since_start);
147 // Will check |exit_function| every |check_interval|. It stops after a check
148 // if either |target_time_since_start| has passed or if |exit_function|
149 // returns true.
150 void RunUntil(TimeDelta target_time_since_start,
151 TimeDelta check_interval,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200152 std::function<bool()> exit_function);
Sebastian Jansson49a78432018-11-20 16:15:29 +0100153 void Start();
154 void Stop();
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200155
156 // Triggers sending of dummy packets over the given nodes.
Artem Titov37d18482019-01-08 15:41:45 +0100157 void TriggerPacketBurst(std::vector<EmulatedNetworkNode*> over_nodes,
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200158 size_t num_packets,
159 size_t packet_size);
160
161 ColumnPrinter TimePrinter();
162 StatesPrinter* CreatePrinter(std::string name,
163 TimeDelta interval,
164 std::vector<ColumnPrinter> printers);
165
166 // Returns the current time.
167 Timestamp Now();
168 // Return the duration of the current session so far.
Sebastian Jansson123f3452019-03-13 11:22:52 +0100169 TimeDelta TimeSinceStart();
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200170
Sebastian Jansson52de8b02019-01-16 17:25:44 +0100171 std::unique_ptr<RtcEventLogOutput> GetLogWriter(std::string name) {
172 if (!log_writer_factory_ || name.empty())
173 return nullptr;
174 return log_writer_factory_->Create(name);
175 }
176 std::unique_ptr<LogWriterFactoryInterface> GetLogWriterFactory(
177 std::string name) {
178 if (!log_writer_factory_ || name.empty())
179 return nullptr;
180 return absl::make_unique<LogWriterFactoryAddPrefix>(
181 log_writer_factory_.get(), name);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200182 }
183
184 private:
185 NullReceiver null_receiver_;
Sebastian Jansson52de8b02019-01-16 17:25:44 +0100186 std::unique_ptr<LogWriterFactoryInterface> log_writer_factory_;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200187 const bool real_time_mode_;
188 SimulatedClock sim_clock_;
189 Clock* clock_;
190 // Event logs use a global clock instance, this is used to override that
191 // instance when not running in real time.
192 rtc::FakeClock event_log_fake_clock_;
193
194 std::vector<std::unique_ptr<CallClient>> clients_;
Sebastian Jansson800e1212018-10-22 11:49:03 +0200195 std::vector<std::unique_ptr<CallClientPair>> client_pairs_;
Artem Titov37d18482019-01-08 15:41:45 +0100196 std::vector<std::unique_ptr<EmulatedNetworkNode>> network_nodes_;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200197 std::vector<std::unique_ptr<CrossTrafficSource>> cross_traffic_sources_;
198 std::vector<std::unique_ptr<VideoStreamPair>> video_streams_;
199 std::vector<std::unique_ptr<AudioStreamPair>> audio_streams_;
200
Sebastian Jansson71a091e2018-09-27 19:08:21 +0200201 std::vector<std::unique_ptr<SimulatedTimeClient>> simulated_time_clients_;
202
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200203 std::vector<std::unique_ptr<RepeatedActivity>> repeated_activities_;
204 std::vector<std::unique_ptr<ActionReceiver>> action_receivers_;
205 std::vector<std::unique_ptr<PendingActivity>> pending_activities_;
206 std::vector<std::unique_ptr<StatesPrinter>> printers_;
207
Sebastian Jansson800e1212018-10-22 11:49:03 +0200208 int64_t next_route_id_ = 40000;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200209 rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory_;
210 rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory_;
211
212 Timestamp start_time_ = Timestamp::PlusInfinity();
213};
214} // namespace test
215} // namespace webrtc
216
217#endif // TEST_SCENARIO_SCENARIO_H_