1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2018 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker #include "test/scenario/scenario.h"
11*d9f75844SAndroid Build Coastguard Worker
12*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include "absl/flags/flag.h"
16*d9f75844SAndroid Build Coastguard Worker #include "absl/flags/parse.h"
17*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
18*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_decoder_factory.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_encoder_factory.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_address.h"
21*d9f75844SAndroid Build Coastguard Worker #include "test/logging/file_log_writer.h"
22*d9f75844SAndroid Build Coastguard Worker #include "test/network/network_emulation.h"
23*d9f75844SAndroid Build Coastguard Worker #include "test/testsupport/file_utils.h"
24*d9f75844SAndroid Build Coastguard Worker
25*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(bool, scenario_logs, false, "Save logs from scenario framework.");
26*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
27*d9f75844SAndroid Build Coastguard Worker scenario_logs_root,
28*d9f75844SAndroid Build Coastguard Worker "",
29*d9f75844SAndroid Build Coastguard Worker "Output root path, based on project root if unset.");
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
32*d9f75844SAndroid Build Coastguard Worker namespace test {
33*d9f75844SAndroid Build Coastguard Worker namespace {
34*d9f75844SAndroid Build Coastguard Worker
GetScenarioLogManager(absl::string_view file_name)35*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FileLogWriterFactory> GetScenarioLogManager(
36*d9f75844SAndroid Build Coastguard Worker absl::string_view file_name) {
37*d9f75844SAndroid Build Coastguard Worker if (absl::GetFlag(FLAGS_scenario_logs) && !file_name.empty()) {
38*d9f75844SAndroid Build Coastguard Worker std::string output_root = absl::GetFlag(FLAGS_scenario_logs_root);
39*d9f75844SAndroid Build Coastguard Worker if (output_root.empty())
40*d9f75844SAndroid Build Coastguard Worker output_root = OutputPath() + "output_data/";
41*d9f75844SAndroid Build Coastguard Worker
42*d9f75844SAndroid Build Coastguard Worker auto base_filename = output_root + std::string(file_name) + ".";
43*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Saving scenario logs to: " << base_filename;
44*d9f75844SAndroid Build Coastguard Worker return std::make_unique<FileLogWriterFactory>(base_filename);
45*d9f75844SAndroid Build Coastguard Worker }
46*d9f75844SAndroid Build Coastguard Worker return nullptr;
47*d9f75844SAndroid Build Coastguard Worker }
48*d9f75844SAndroid Build Coastguard Worker } // namespace
49*d9f75844SAndroid Build Coastguard Worker
Scenario()50*d9f75844SAndroid Build Coastguard Worker Scenario::Scenario()
51*d9f75844SAndroid Build Coastguard Worker : Scenario(std::unique_ptr<LogWriterFactoryInterface>(),
52*d9f75844SAndroid Build Coastguard Worker /*real_time=*/false) {}
53*d9f75844SAndroid Build Coastguard Worker
Scenario(const testing::TestInfo * test_info)54*d9f75844SAndroid Build Coastguard Worker Scenario::Scenario(const testing::TestInfo* test_info)
55*d9f75844SAndroid Build Coastguard Worker : Scenario(std::string(test_info->test_suite_name()) + "/" +
56*d9f75844SAndroid Build Coastguard Worker test_info->name()) {}
57*d9f75844SAndroid Build Coastguard Worker
Scenario(absl::string_view file_name)58*d9f75844SAndroid Build Coastguard Worker Scenario::Scenario(absl::string_view file_name)
59*d9f75844SAndroid Build Coastguard Worker : Scenario(file_name, /*real_time=*/false) {}
60*d9f75844SAndroid Build Coastguard Worker
Scenario(absl::string_view file_name,bool real_time)61*d9f75844SAndroid Build Coastguard Worker Scenario::Scenario(absl::string_view file_name, bool real_time)
62*d9f75844SAndroid Build Coastguard Worker : Scenario(GetScenarioLogManager(file_name), real_time) {}
63*d9f75844SAndroid Build Coastguard Worker
Scenario(std::unique_ptr<LogWriterFactoryInterface> log_writer_factory,bool real_time)64*d9f75844SAndroid Build Coastguard Worker Scenario::Scenario(
65*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<LogWriterFactoryInterface> log_writer_factory,
66*d9f75844SAndroid Build Coastguard Worker bool real_time)
67*d9f75844SAndroid Build Coastguard Worker : log_writer_factory_(std::move(log_writer_factory)),
68*d9f75844SAndroid Build Coastguard Worker network_manager_(real_time ? TimeMode::kRealTime : TimeMode::kSimulated,
69*d9f75844SAndroid Build Coastguard Worker EmulatedNetworkStatsGatheringMode::kDefault),
70*d9f75844SAndroid Build Coastguard Worker clock_(network_manager_.time_controller()->GetClock()),
71*d9f75844SAndroid Build Coastguard Worker audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()),
72*d9f75844SAndroid Build Coastguard Worker audio_encoder_factory_(CreateBuiltinAudioEncoderFactory()),
73*d9f75844SAndroid Build Coastguard Worker task_queue_(network_manager_.time_controller()
74*d9f75844SAndroid Build Coastguard Worker ->GetTaskQueueFactory()
75*d9f75844SAndroid Build Coastguard Worker ->CreateTaskQueue("Scenario",
76*d9f75844SAndroid Build Coastguard Worker TaskQueueFactory::Priority::NORMAL)) {}
77*d9f75844SAndroid Build Coastguard Worker
~Scenario()78*d9f75844SAndroid Build Coastguard Worker Scenario::~Scenario() {
79*d9f75844SAndroid Build Coastguard Worker if (start_time_.IsFinite())
80*d9f75844SAndroid Build Coastguard Worker Stop();
81*d9f75844SAndroid Build Coastguard Worker for (auto& call_client : clients_) {
82*d9f75844SAndroid Build Coastguard Worker call_client->transport_->Disconnect();
83*d9f75844SAndroid Build Coastguard Worker call_client->UnBind();
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker }
86*d9f75844SAndroid Build Coastguard Worker
TimePrinter()87*d9f75844SAndroid Build Coastguard Worker ColumnPrinter Scenario::TimePrinter() {
88*d9f75844SAndroid Build Coastguard Worker return ColumnPrinter::Lambda(
89*d9f75844SAndroid Build Coastguard Worker "time",
90*d9f75844SAndroid Build Coastguard Worker [this](rtc::SimpleStringBuilder& sb) {
91*d9f75844SAndroid Build Coastguard Worker sb.AppendFormat("%.3lf", Now().seconds<double>());
92*d9f75844SAndroid Build Coastguard Worker },
93*d9f75844SAndroid Build Coastguard Worker 32);
94*d9f75844SAndroid Build Coastguard Worker }
95*d9f75844SAndroid Build Coastguard Worker
CreatePrinter(absl::string_view name,TimeDelta interval,std::vector<ColumnPrinter> printers)96*d9f75844SAndroid Build Coastguard Worker StatesPrinter* Scenario::CreatePrinter(absl::string_view name,
97*d9f75844SAndroid Build Coastguard Worker TimeDelta interval,
98*d9f75844SAndroid Build Coastguard Worker std::vector<ColumnPrinter> printers) {
99*d9f75844SAndroid Build Coastguard Worker std::vector<ColumnPrinter> all_printers{TimePrinter()};
100*d9f75844SAndroid Build Coastguard Worker for (auto& printer : printers)
101*d9f75844SAndroid Build Coastguard Worker all_printers.push_back(printer);
102*d9f75844SAndroid Build Coastguard Worker StatesPrinter* printer = new StatesPrinter(GetLogWriter(name), all_printers);
103*d9f75844SAndroid Build Coastguard Worker printers_.emplace_back(printer);
104*d9f75844SAndroid Build Coastguard Worker printer->PrintHeaders();
105*d9f75844SAndroid Build Coastguard Worker if (interval.IsFinite())
106*d9f75844SAndroid Build Coastguard Worker Every(interval, [printer] { printer->PrintRow(); });
107*d9f75844SAndroid Build Coastguard Worker return printer;
108*d9f75844SAndroid Build Coastguard Worker }
109*d9f75844SAndroid Build Coastguard Worker
CreateClient(absl::string_view name,CallClientConfig config)110*d9f75844SAndroid Build Coastguard Worker CallClient* Scenario::CreateClient(absl::string_view name,
111*d9f75844SAndroid Build Coastguard Worker CallClientConfig config) {
112*d9f75844SAndroid Build Coastguard Worker CallClient* client = new CallClient(network_manager_.time_controller(),
113*d9f75844SAndroid Build Coastguard Worker GetLogWriterFactory(name), config);
114*d9f75844SAndroid Build Coastguard Worker if (config.transport.state_log_interval.IsFinite()) {
115*d9f75844SAndroid Build Coastguard Worker Every(config.transport.state_log_interval, [this, client]() {
116*d9f75844SAndroid Build Coastguard Worker client->network_controller_factory_.LogCongestionControllerStats(Now());
117*d9f75844SAndroid Build Coastguard Worker });
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker clients_.emplace_back(client);
120*d9f75844SAndroid Build Coastguard Worker return client;
121*d9f75844SAndroid Build Coastguard Worker }
122*d9f75844SAndroid Build Coastguard Worker
CreateClient(absl::string_view name,std::function<void (CallClientConfig *)> config_modifier)123*d9f75844SAndroid Build Coastguard Worker CallClient* Scenario::CreateClient(
124*d9f75844SAndroid Build Coastguard Worker absl::string_view name,
125*d9f75844SAndroid Build Coastguard Worker std::function<void(CallClientConfig*)> config_modifier) {
126*d9f75844SAndroid Build Coastguard Worker CallClientConfig config;
127*d9f75844SAndroid Build Coastguard Worker config_modifier(&config);
128*d9f75844SAndroid Build Coastguard Worker return CreateClient(name, config);
129*d9f75844SAndroid Build Coastguard Worker }
130*d9f75844SAndroid Build Coastguard Worker
CreateRoutes(CallClient * first,std::vector<EmulatedNetworkNode * > send_link,CallClient * second,std::vector<EmulatedNetworkNode * > return_link)131*d9f75844SAndroid Build Coastguard Worker CallClientPair* Scenario::CreateRoutes(
132*d9f75844SAndroid Build Coastguard Worker CallClient* first,
133*d9f75844SAndroid Build Coastguard Worker std::vector<EmulatedNetworkNode*> send_link,
134*d9f75844SAndroid Build Coastguard Worker CallClient* second,
135*d9f75844SAndroid Build Coastguard Worker std::vector<EmulatedNetworkNode*> return_link) {
136*d9f75844SAndroid Build Coastguard Worker return CreateRoutes(first, send_link,
137*d9f75844SAndroid Build Coastguard Worker DataSize::Bytes(PacketOverhead::kDefault), second,
138*d9f75844SAndroid Build Coastguard Worker return_link, DataSize::Bytes(PacketOverhead::kDefault));
139*d9f75844SAndroid Build Coastguard Worker }
140*d9f75844SAndroid Build Coastguard Worker
CreateRoutes(CallClient * first,std::vector<EmulatedNetworkNode * > send_link,DataSize first_overhead,CallClient * second,std::vector<EmulatedNetworkNode * > return_link,DataSize second_overhead)141*d9f75844SAndroid Build Coastguard Worker CallClientPair* Scenario::CreateRoutes(
142*d9f75844SAndroid Build Coastguard Worker CallClient* first,
143*d9f75844SAndroid Build Coastguard Worker std::vector<EmulatedNetworkNode*> send_link,
144*d9f75844SAndroid Build Coastguard Worker DataSize first_overhead,
145*d9f75844SAndroid Build Coastguard Worker CallClient* second,
146*d9f75844SAndroid Build Coastguard Worker std::vector<EmulatedNetworkNode*> return_link,
147*d9f75844SAndroid Build Coastguard Worker DataSize second_overhead) {
148*d9f75844SAndroid Build Coastguard Worker CallClientPair* client_pair = new CallClientPair(first, second);
149*d9f75844SAndroid Build Coastguard Worker ChangeRoute(client_pair->forward(), send_link, first_overhead);
150*d9f75844SAndroid Build Coastguard Worker ChangeRoute(client_pair->reverse(), return_link, second_overhead);
151*d9f75844SAndroid Build Coastguard Worker client_pairs_.emplace_back(client_pair);
152*d9f75844SAndroid Build Coastguard Worker return client_pair;
153*d9f75844SAndroid Build Coastguard Worker }
154*d9f75844SAndroid Build Coastguard Worker
ChangeRoute(std::pair<CallClient *,CallClient * > clients,std::vector<EmulatedNetworkNode * > over_nodes)155*d9f75844SAndroid Build Coastguard Worker void Scenario::ChangeRoute(std::pair<CallClient*, CallClient*> clients,
156*d9f75844SAndroid Build Coastguard Worker std::vector<EmulatedNetworkNode*> over_nodes) {
157*d9f75844SAndroid Build Coastguard Worker ChangeRoute(clients, over_nodes, DataSize::Bytes(PacketOverhead::kDefault));
158*d9f75844SAndroid Build Coastguard Worker }
159*d9f75844SAndroid Build Coastguard Worker
ChangeRoute(std::pair<CallClient *,CallClient * > clients,std::vector<EmulatedNetworkNode * > over_nodes,DataSize overhead)160*d9f75844SAndroid Build Coastguard Worker void Scenario::ChangeRoute(std::pair<CallClient*, CallClient*> clients,
161*d9f75844SAndroid Build Coastguard Worker std::vector<EmulatedNetworkNode*> over_nodes,
162*d9f75844SAndroid Build Coastguard Worker DataSize overhead) {
163*d9f75844SAndroid Build Coastguard Worker EmulatedRoute* route = network_manager_.CreateRoute(over_nodes);
164*d9f75844SAndroid Build Coastguard Worker uint16_t port = clients.second->Bind(route->to);
165*d9f75844SAndroid Build Coastguard Worker auto addr = rtc::SocketAddress(route->to->GetPeerLocalAddress(), port);
166*d9f75844SAndroid Build Coastguard Worker clients.first->transport_->Connect(route->from, addr, overhead);
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker
CreateSimulationNode(std::function<void (NetworkSimulationConfig *)> config_modifier)169*d9f75844SAndroid Build Coastguard Worker EmulatedNetworkNode* Scenario::CreateSimulationNode(
170*d9f75844SAndroid Build Coastguard Worker std::function<void(NetworkSimulationConfig*)> config_modifier) {
171*d9f75844SAndroid Build Coastguard Worker NetworkSimulationConfig config;
172*d9f75844SAndroid Build Coastguard Worker config_modifier(&config);
173*d9f75844SAndroid Build Coastguard Worker return CreateSimulationNode(config);
174*d9f75844SAndroid Build Coastguard Worker }
175*d9f75844SAndroid Build Coastguard Worker
CreateSimulationNode(NetworkSimulationConfig config)176*d9f75844SAndroid Build Coastguard Worker EmulatedNetworkNode* Scenario::CreateSimulationNode(
177*d9f75844SAndroid Build Coastguard Worker NetworkSimulationConfig config) {
178*d9f75844SAndroid Build Coastguard Worker return network_manager_.CreateEmulatedNode(
179*d9f75844SAndroid Build Coastguard Worker SimulationNode::CreateBehavior(config));
180*d9f75844SAndroid Build Coastguard Worker }
181*d9f75844SAndroid Build Coastguard Worker
CreateMutableSimulationNode(std::function<void (NetworkSimulationConfig *)> config_modifier)182*d9f75844SAndroid Build Coastguard Worker SimulationNode* Scenario::CreateMutableSimulationNode(
183*d9f75844SAndroid Build Coastguard Worker std::function<void(NetworkSimulationConfig*)> config_modifier) {
184*d9f75844SAndroid Build Coastguard Worker NetworkSimulationConfig config;
185*d9f75844SAndroid Build Coastguard Worker config_modifier(&config);
186*d9f75844SAndroid Build Coastguard Worker return CreateMutableSimulationNode(config);
187*d9f75844SAndroid Build Coastguard Worker }
188*d9f75844SAndroid Build Coastguard Worker
CreateMutableSimulationNode(NetworkSimulationConfig config)189*d9f75844SAndroid Build Coastguard Worker SimulationNode* Scenario::CreateMutableSimulationNode(
190*d9f75844SAndroid Build Coastguard Worker NetworkSimulationConfig config) {
191*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SimulatedNetwork> behavior =
192*d9f75844SAndroid Build Coastguard Worker SimulationNode::CreateBehavior(config);
193*d9f75844SAndroid Build Coastguard Worker SimulatedNetwork* behavior_ptr = behavior.get();
194*d9f75844SAndroid Build Coastguard Worker auto* emulated_node =
195*d9f75844SAndroid Build Coastguard Worker network_manager_.CreateEmulatedNode(std::move(behavior));
196*d9f75844SAndroid Build Coastguard Worker simulation_nodes_.emplace_back(
197*d9f75844SAndroid Build Coastguard Worker new SimulationNode(config, behavior_ptr, emulated_node));
198*d9f75844SAndroid Build Coastguard Worker return simulation_nodes_.back().get();
199*d9f75844SAndroid Build Coastguard Worker }
200*d9f75844SAndroid Build Coastguard Worker
TriggerPacketBurst(std::vector<EmulatedNetworkNode * > over_nodes,size_t num_packets,size_t packet_size)201*d9f75844SAndroid Build Coastguard Worker void Scenario::TriggerPacketBurst(std::vector<EmulatedNetworkNode*> over_nodes,
202*d9f75844SAndroid Build Coastguard Worker size_t num_packets,
203*d9f75844SAndroid Build Coastguard Worker size_t packet_size) {
204*d9f75844SAndroid Build Coastguard Worker network_manager_.CreateCrossTrafficRoute(over_nodes)
205*d9f75844SAndroid Build Coastguard Worker ->TriggerPacketBurst(num_packets, packet_size);
206*d9f75844SAndroid Build Coastguard Worker }
207*d9f75844SAndroid Build Coastguard Worker
NetworkDelayedAction(std::vector<EmulatedNetworkNode * > over_nodes,size_t packet_size,std::function<void ()> action)208*d9f75844SAndroid Build Coastguard Worker void Scenario::NetworkDelayedAction(
209*d9f75844SAndroid Build Coastguard Worker std::vector<EmulatedNetworkNode*> over_nodes,
210*d9f75844SAndroid Build Coastguard Worker size_t packet_size,
211*d9f75844SAndroid Build Coastguard Worker std::function<void()> action) {
212*d9f75844SAndroid Build Coastguard Worker network_manager_.CreateCrossTrafficRoute(over_nodes)
213*d9f75844SAndroid Build Coastguard Worker ->NetworkDelayedAction(packet_size, action);
214*d9f75844SAndroid Build Coastguard Worker }
215*d9f75844SAndroid Build Coastguard Worker
CreateVideoStream(std::pair<CallClient *,CallClient * > clients,std::function<void (VideoStreamConfig *)> config_modifier)216*d9f75844SAndroid Build Coastguard Worker VideoStreamPair* Scenario::CreateVideoStream(
217*d9f75844SAndroid Build Coastguard Worker std::pair<CallClient*, CallClient*> clients,
218*d9f75844SAndroid Build Coastguard Worker std::function<void(VideoStreamConfig*)> config_modifier) {
219*d9f75844SAndroid Build Coastguard Worker VideoStreamConfig config;
220*d9f75844SAndroid Build Coastguard Worker config_modifier(&config);
221*d9f75844SAndroid Build Coastguard Worker return CreateVideoStream(clients, config);
222*d9f75844SAndroid Build Coastguard Worker }
223*d9f75844SAndroid Build Coastguard Worker
CreateVideoStream(std::pair<CallClient *,CallClient * > clients,VideoStreamConfig config)224*d9f75844SAndroid Build Coastguard Worker VideoStreamPair* Scenario::CreateVideoStream(
225*d9f75844SAndroid Build Coastguard Worker std::pair<CallClient*, CallClient*> clients,
226*d9f75844SAndroid Build Coastguard Worker VideoStreamConfig config) {
227*d9f75844SAndroid Build Coastguard Worker video_streams_.emplace_back(
228*d9f75844SAndroid Build Coastguard Worker new VideoStreamPair(clients.first, clients.second, config));
229*d9f75844SAndroid Build Coastguard Worker return video_streams_.back().get();
230*d9f75844SAndroid Build Coastguard Worker }
231*d9f75844SAndroid Build Coastguard Worker
CreateAudioStream(std::pair<CallClient *,CallClient * > clients,std::function<void (AudioStreamConfig *)> config_modifier)232*d9f75844SAndroid Build Coastguard Worker AudioStreamPair* Scenario::CreateAudioStream(
233*d9f75844SAndroid Build Coastguard Worker std::pair<CallClient*, CallClient*> clients,
234*d9f75844SAndroid Build Coastguard Worker std::function<void(AudioStreamConfig*)> config_modifier) {
235*d9f75844SAndroid Build Coastguard Worker AudioStreamConfig config;
236*d9f75844SAndroid Build Coastguard Worker config_modifier(&config);
237*d9f75844SAndroid Build Coastguard Worker return CreateAudioStream(clients, config);
238*d9f75844SAndroid Build Coastguard Worker }
239*d9f75844SAndroid Build Coastguard Worker
CreateAudioStream(std::pair<CallClient *,CallClient * > clients,AudioStreamConfig config)240*d9f75844SAndroid Build Coastguard Worker AudioStreamPair* Scenario::CreateAudioStream(
241*d9f75844SAndroid Build Coastguard Worker std::pair<CallClient*, CallClient*> clients,
242*d9f75844SAndroid Build Coastguard Worker AudioStreamConfig config) {
243*d9f75844SAndroid Build Coastguard Worker audio_streams_.emplace_back(
244*d9f75844SAndroid Build Coastguard Worker new AudioStreamPair(clients.first, audio_encoder_factory_, clients.second,
245*d9f75844SAndroid Build Coastguard Worker audio_decoder_factory_, config));
246*d9f75844SAndroid Build Coastguard Worker return audio_streams_.back().get();
247*d9f75844SAndroid Build Coastguard Worker }
248*d9f75844SAndroid Build Coastguard Worker
Every(TimeDelta interval,absl::AnyInvocable<void (TimeDelta)> function)249*d9f75844SAndroid Build Coastguard Worker void Scenario::Every(TimeDelta interval,
250*d9f75844SAndroid Build Coastguard Worker absl::AnyInvocable<void(TimeDelta)> function) {
251*d9f75844SAndroid Build Coastguard Worker RepeatingTaskHandle::DelayedStart(
252*d9f75844SAndroid Build Coastguard Worker task_queue_.get(), interval,
253*d9f75844SAndroid Build Coastguard Worker [interval, function = std::move(function)]() mutable {
254*d9f75844SAndroid Build Coastguard Worker function(interval);
255*d9f75844SAndroid Build Coastguard Worker return interval;
256*d9f75844SAndroid Build Coastguard Worker });
257*d9f75844SAndroid Build Coastguard Worker }
258*d9f75844SAndroid Build Coastguard Worker
Every(TimeDelta interval,absl::AnyInvocable<void ()> function)259*d9f75844SAndroid Build Coastguard Worker void Scenario::Every(TimeDelta interval, absl::AnyInvocable<void()> function) {
260*d9f75844SAndroid Build Coastguard Worker RepeatingTaskHandle::DelayedStart(
261*d9f75844SAndroid Build Coastguard Worker task_queue_.get(), interval,
262*d9f75844SAndroid Build Coastguard Worker [interval, function = std::move(function)]() mutable {
263*d9f75844SAndroid Build Coastguard Worker function();
264*d9f75844SAndroid Build Coastguard Worker return interval;
265*d9f75844SAndroid Build Coastguard Worker });
266*d9f75844SAndroid Build Coastguard Worker }
267*d9f75844SAndroid Build Coastguard Worker
Post(absl::AnyInvocable<void ()&&> function)268*d9f75844SAndroid Build Coastguard Worker void Scenario::Post(absl::AnyInvocable<void() &&> function) {
269*d9f75844SAndroid Build Coastguard Worker task_queue_->PostTask(std::move(function));
270*d9f75844SAndroid Build Coastguard Worker }
271*d9f75844SAndroid Build Coastguard Worker
At(TimeDelta offset,absl::AnyInvocable<void ()&&> function)272*d9f75844SAndroid Build Coastguard Worker void Scenario::At(TimeDelta offset, absl::AnyInvocable<void() &&> function) {
273*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_GT(offset, TimeSinceStart());
274*d9f75844SAndroid Build Coastguard Worker task_queue_->PostDelayedTask(std::move(function), TimeUntilTarget(offset));
275*d9f75844SAndroid Build Coastguard Worker }
276*d9f75844SAndroid Build Coastguard Worker
RunFor(TimeDelta duration)277*d9f75844SAndroid Build Coastguard Worker void Scenario::RunFor(TimeDelta duration) {
278*d9f75844SAndroid Build Coastguard Worker if (start_time_.IsInfinite())
279*d9f75844SAndroid Build Coastguard Worker Start();
280*d9f75844SAndroid Build Coastguard Worker network_manager_.time_controller()->AdvanceTime(duration);
281*d9f75844SAndroid Build Coastguard Worker }
282*d9f75844SAndroid Build Coastguard Worker
RunUntil(TimeDelta target_time_since_start)283*d9f75844SAndroid Build Coastguard Worker void Scenario::RunUntil(TimeDelta target_time_since_start) {
284*d9f75844SAndroid Build Coastguard Worker RunFor(TimeUntilTarget(target_time_since_start));
285*d9f75844SAndroid Build Coastguard Worker }
286*d9f75844SAndroid Build Coastguard Worker
RunUntil(TimeDelta target_time_since_start,TimeDelta check_interval,std::function<bool ()> exit_function)287*d9f75844SAndroid Build Coastguard Worker void Scenario::RunUntil(TimeDelta target_time_since_start,
288*d9f75844SAndroid Build Coastguard Worker TimeDelta check_interval,
289*d9f75844SAndroid Build Coastguard Worker std::function<bool()> exit_function) {
290*d9f75844SAndroid Build Coastguard Worker if (start_time_.IsInfinite())
291*d9f75844SAndroid Build Coastguard Worker Start();
292*d9f75844SAndroid Build Coastguard Worker while (check_interval >= TimeUntilTarget(target_time_since_start)) {
293*d9f75844SAndroid Build Coastguard Worker network_manager_.time_controller()->AdvanceTime(check_interval);
294*d9f75844SAndroid Build Coastguard Worker if (exit_function())
295*d9f75844SAndroid Build Coastguard Worker return;
296*d9f75844SAndroid Build Coastguard Worker }
297*d9f75844SAndroid Build Coastguard Worker network_manager_.time_controller()->AdvanceTime(
298*d9f75844SAndroid Build Coastguard Worker TimeUntilTarget(target_time_since_start));
299*d9f75844SAndroid Build Coastguard Worker }
300*d9f75844SAndroid Build Coastguard Worker
Start()301*d9f75844SAndroid Build Coastguard Worker void Scenario::Start() {
302*d9f75844SAndroid Build Coastguard Worker start_time_ = clock_->CurrentTime();
303*d9f75844SAndroid Build Coastguard Worker for (auto& stream_pair : video_streams_)
304*d9f75844SAndroid Build Coastguard Worker stream_pair->receive()->Start();
305*d9f75844SAndroid Build Coastguard Worker for (auto& stream_pair : audio_streams_)
306*d9f75844SAndroid Build Coastguard Worker stream_pair->receive()->Start();
307*d9f75844SAndroid Build Coastguard Worker for (auto& stream_pair : video_streams_) {
308*d9f75844SAndroid Build Coastguard Worker if (stream_pair->config_.autostart) {
309*d9f75844SAndroid Build Coastguard Worker stream_pair->send()->Start();
310*d9f75844SAndroid Build Coastguard Worker }
311*d9f75844SAndroid Build Coastguard Worker }
312*d9f75844SAndroid Build Coastguard Worker for (auto& stream_pair : audio_streams_) {
313*d9f75844SAndroid Build Coastguard Worker if (stream_pair->config_.autostart) {
314*d9f75844SAndroid Build Coastguard Worker stream_pair->send()->Start();
315*d9f75844SAndroid Build Coastguard Worker }
316*d9f75844SAndroid Build Coastguard Worker }
317*d9f75844SAndroid Build Coastguard Worker }
318*d9f75844SAndroid Build Coastguard Worker
Stop()319*d9f75844SAndroid Build Coastguard Worker void Scenario::Stop() {
320*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(start_time_.IsFinite());
321*d9f75844SAndroid Build Coastguard Worker for (auto& stream_pair : video_streams_) {
322*d9f75844SAndroid Build Coastguard Worker stream_pair->send()->Stop();
323*d9f75844SAndroid Build Coastguard Worker }
324*d9f75844SAndroid Build Coastguard Worker for (auto& stream_pair : audio_streams_)
325*d9f75844SAndroid Build Coastguard Worker stream_pair->send()->Stop();
326*d9f75844SAndroid Build Coastguard Worker for (auto& stream_pair : video_streams_)
327*d9f75844SAndroid Build Coastguard Worker stream_pair->receive()->Stop();
328*d9f75844SAndroid Build Coastguard Worker for (auto& stream_pair : audio_streams_)
329*d9f75844SAndroid Build Coastguard Worker stream_pair->receive()->Stop();
330*d9f75844SAndroid Build Coastguard Worker start_time_ = Timestamp::PlusInfinity();
331*d9f75844SAndroid Build Coastguard Worker }
332*d9f75844SAndroid Build Coastguard Worker
Now()333*d9f75844SAndroid Build Coastguard Worker Timestamp Scenario::Now() {
334*d9f75844SAndroid Build Coastguard Worker return clock_->CurrentTime();
335*d9f75844SAndroid Build Coastguard Worker }
336*d9f75844SAndroid Build Coastguard Worker
TimeSinceStart()337*d9f75844SAndroid Build Coastguard Worker TimeDelta Scenario::TimeSinceStart() {
338*d9f75844SAndroid Build Coastguard Worker if (start_time_.IsInfinite())
339*d9f75844SAndroid Build Coastguard Worker return TimeDelta::Zero();
340*d9f75844SAndroid Build Coastguard Worker return Now() - start_time_;
341*d9f75844SAndroid Build Coastguard Worker }
342*d9f75844SAndroid Build Coastguard Worker
TimeUntilTarget(TimeDelta target_time_offset)343*d9f75844SAndroid Build Coastguard Worker TimeDelta Scenario::TimeUntilTarget(TimeDelta target_time_offset) {
344*d9f75844SAndroid Build Coastguard Worker return target_time_offset - TimeSinceStart();
345*d9f75844SAndroid Build Coastguard Worker }
346*d9f75844SAndroid Build Coastguard Worker
347*d9f75844SAndroid Build Coastguard Worker } // namespace test
348*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
349