1 /*
2 * Copyright (c) 2019 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 #include "test/peer_scenario/peer_scenario.h"
11
12 #include "absl/flags/flag.h"
13 #include "absl/memory/memory.h"
14 #include "rtc_base/null_socket_server.h"
15 #include "rtc_base/string_encode.h"
16 #include "rtc_base/strings/string_builder.h"
17 #include "test/logging/file_log_writer.h"
18 #include "test/testsupport/file_utils.h"
19 #include "test/time_controller/real_time_controller.h"
20 #include "test/time_controller/simulated_time_controller.h"
21
22 ABSL_FLAG(bool, peer_logs, false, "Save logs from peer scenario framework.");
23 ABSL_FLAG(std::string,
24 peer_logs_root,
25 "",
26 "Output root path, based on project root if unset.");
27
28 namespace webrtc {
29 namespace test {
30 namespace {
GetPeerScenarioLogManager(std::string file_name)31 std::unique_ptr<FileLogWriterFactory> GetPeerScenarioLogManager(
32 std::string file_name) {
33 if (absl::GetFlag(FLAGS_peer_logs) && !file_name.empty()) {
34 std::string output_root = absl::GetFlag(FLAGS_peer_logs_root);
35 if (output_root.empty())
36 output_root = OutputPath() + "output_data/";
37
38 auto base_filename = output_root + file_name + ".";
39 RTC_LOG(LS_INFO) << "Saving peer scenario logs to: " << base_filename;
40 return std::make_unique<FileLogWriterFactory>(base_filename);
41 }
42 return nullptr;
43 }
44 } // namespace
45
PeerScenario(const testing::TestInfo & test_info,TimeMode mode)46 PeerScenario::PeerScenario(const testing::TestInfo& test_info, TimeMode mode)
47 : PeerScenario(
48 std::string(test_info.test_suite_name()) + "/" + test_info.name(),
49 mode) {}
50
PeerScenario(std::string file_name,TimeMode mode)51 PeerScenario::PeerScenario(std::string file_name, TimeMode mode)
52 : PeerScenario(GetPeerScenarioLogManager(file_name), mode) {}
53
PeerScenario(std::unique_ptr<LogWriterFactoryInterface> log_writer_manager,TimeMode mode)54 PeerScenario::PeerScenario(
55 std::unique_ptr<LogWriterFactoryInterface> log_writer_manager,
56 TimeMode mode)
57 : log_writer_manager_(std::move(log_writer_manager)),
58 net_(mode),
59 signaling_thread_(net_.time_controller()->GetMainThread()) {}
60
CreateClient(PeerScenarioClient::Config config)61 PeerScenarioClient* PeerScenario::CreateClient(
62 PeerScenarioClient::Config config) {
63 return CreateClient(
64 std::string("client_") + rtc::ToString(peer_clients_.size() + 1), config);
65 }
66
CreateClient(std::string name,PeerScenarioClient::Config config)67 PeerScenarioClient* PeerScenario::CreateClient(
68 std::string name,
69 PeerScenarioClient::Config config) {
70 peer_clients_.emplace_back(net(), signaling_thread_,
71 GetLogWriterFactory(name), config);
72 return &peer_clients_.back();
73 }
74
ConnectSignaling(PeerScenarioClient * caller,PeerScenarioClient * callee,std::vector<EmulatedNetworkNode * > send_link,std::vector<EmulatedNetworkNode * > ret_link)75 SignalingRoute PeerScenario::ConnectSignaling(
76 PeerScenarioClient* caller,
77 PeerScenarioClient* callee,
78 std::vector<EmulatedNetworkNode*> send_link,
79 std::vector<EmulatedNetworkNode*> ret_link) {
80 return SignalingRoute(caller, callee, net_.CreateTrafficRoute(send_link),
81 net_.CreateTrafficRoute(ret_link));
82 }
83
SimpleConnection(PeerScenarioClient * caller,PeerScenarioClient * callee,std::vector<EmulatedNetworkNode * > send_link,std::vector<EmulatedNetworkNode * > ret_link)84 void PeerScenario::SimpleConnection(
85 PeerScenarioClient* caller,
86 PeerScenarioClient* callee,
87 std::vector<EmulatedNetworkNode*> send_link,
88 std::vector<EmulatedNetworkNode*> ret_link) {
89 net()->CreateRoute(caller->endpoint(), send_link, callee->endpoint());
90 net()->CreateRoute(callee->endpoint(), ret_link, caller->endpoint());
91 auto signaling = ConnectSignaling(caller, callee, send_link, ret_link);
92 signaling.StartIceSignaling();
93 std::atomic<bool> done(false);
94 signaling.NegotiateSdp(
95 [&](const SessionDescriptionInterface&) { done = true; });
96 RTC_CHECK(WaitAndProcess(&done));
97 }
98
AttachVideoQualityAnalyzer(VideoQualityAnalyzer * analyzer,VideoTrackInterface * send_track,PeerScenarioClient * receiver)99 void PeerScenario::AttachVideoQualityAnalyzer(VideoQualityAnalyzer* analyzer,
100 VideoTrackInterface* send_track,
101 PeerScenarioClient* receiver) {
102 video_quality_pairs_.emplace_back(clock(), analyzer);
103 auto pair = &video_quality_pairs_.back();
104 send_track->AddOrUpdateSink(&pair->capture_tap_, rtc::VideoSinkWants());
105 receiver->AddVideoReceiveSink(send_track->id(), &pair->decode_tap_);
106 }
107
WaitAndProcess(std::atomic<bool> * event,TimeDelta max_duration)108 bool PeerScenario::WaitAndProcess(std::atomic<bool>* event,
109 TimeDelta max_duration) {
110 return net_.time_controller()->Wait([event] { return event->load(); },
111 max_duration);
112 }
113
ProcessMessages(TimeDelta duration)114 void PeerScenario::ProcessMessages(TimeDelta duration) {
115 net_.time_controller()->AdvanceTime(duration);
116 }
117
GetLogWriterFactory(std::string name)118 std::unique_ptr<LogWriterFactoryInterface> PeerScenario::GetLogWriterFactory(
119 std::string name) {
120 if (!log_writer_manager_ || name.empty())
121 return nullptr;
122 return std::make_unique<LogWriterFactoryAddPrefix>(log_writer_manager_.get(),
123 name);
124 }
125
126 } // namespace test
127 } // namespace webrtc
128