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 #ifndef TEST_PEER_SCENARIO_PEER_SCENARIO_H_ 11 #define TEST_PEER_SCENARIO_PEER_SCENARIO_H_ 12 13 // The peer connection scenario test framework enables writing end to end unit 14 // tests on the peer connection level. It's similar to the Scenario test but 15 // uses the full stack, including SDP and ICE negotiation. This ensures that 16 // features work end to end. It's also diffferent from the other tests on peer 17 // connection level in that it does not rely on any mocks or fakes other than 18 // for media input and networking. Additionally it provides direct access to the 19 // underlying peer connection class. 20 21 #include <list> 22 #include <vector> 23 24 #include "api/test/time_controller.h" 25 #include "test/gtest.h" 26 #include "test/logging/log_writer.h" 27 #include "test/network/network_emulation_manager.h" 28 #include "test/peer_scenario/peer_scenario_client.h" 29 #include "test/peer_scenario/signaling_route.h" 30 #include "test/scenario/stats_collection.h" 31 #include "test/scenario/video_frame_matcher.h" 32 33 namespace webrtc { 34 namespace test { 35 // The PeerScenario class represents a PeerConnection simulation scenario. The 36 // main purpose is to maintain ownership and ensure safe destruction order of 37 // clients and network emulation. Additionally it reduces the amount of boiler 38 // plate requited for some actions. For example usage see the existing tests 39 // using this class. Note that it should be used from a single calling thread. 40 // This thread will also be assigned as the signaling thread for all peer 41 // connections that are created. This means that the process methods must be 42 // used when waiting to ensure that messages are processed on the signaling 43 // thread. 44 class PeerScenario { 45 public: 46 // The name is used for log output when those are enabled by the --peer_logs 47 // command line flag. Optionally, the TestInfo struct available in gtest can 48 // be used to automatically generate a path based on the test name. 49 explicit PeerScenario(const testing::TestInfo& test_info, 50 TimeMode mode = TimeMode::kSimulated); 51 explicit PeerScenario(std::string file_name, 52 TimeMode mode = TimeMode::kSimulated); 53 explicit PeerScenario( 54 std::unique_ptr<LogWriterFactoryInterface> log_writer_manager, 55 TimeMode mode = TimeMode::kSimulated); 56 net()57 NetworkEmulationManagerImpl* net() { return &net_; } 58 59 // Creates a client wrapping a peer connection conforming to the given config. 60 // The client will share the signaling thread with the scenario. To maintain 61 // control of destruction order, ownership is kept within the scenario. 62 PeerScenarioClient* CreateClient(PeerScenarioClient::Config config); 63 PeerScenarioClient* CreateClient(std::string name, 64 PeerScenarioClient::Config config); 65 66 // Sets up a signaling route that can be used for SDP and ICE. 67 SignalingRoute ConnectSignaling(PeerScenarioClient* caller, 68 PeerScenarioClient* callee, 69 std::vector<EmulatedNetworkNode*> send_link, 70 std::vector<EmulatedNetworkNode*> ret_link); 71 72 // Connects two clients over given links. This will also start ICE signaling 73 // and SDP negotiation with default behavior. For customized behavior, 74 // ConnectSignaling should be used to allow more detailed control, for 75 // instance to allow different signaling and media routes. 76 void SimpleConnection(PeerScenarioClient* caller, 77 PeerScenarioClient* callee, 78 std::vector<EmulatedNetworkNode*> send_link, 79 std::vector<EmulatedNetworkNode*> ret_link); 80 81 // Starts feeding the results of comparing captured frames from |send_track| 82 // with decoded frames on |receiver| to |analyzer|. 83 // TODO(srte): Provide a way to detach to allow removal of tracks. 84 void AttachVideoQualityAnalyzer(VideoQualityAnalyzer* analyzer, 85 VideoTrackInterface* send_track, 86 PeerScenarioClient* receiver); 87 88 // Waits on |event| while processing messages on the signaling thread. 89 bool WaitAndProcess(std::atomic<bool>* event, 90 TimeDelta max_duration = TimeDelta::Seconds(5)); 91 92 // Process messages on the signaling thread for the given duration. 93 void ProcessMessages(TimeDelta duration); 94 95 private: 96 // Helper struct to maintain ownership of the matcher and taps. 97 struct PeerVideoQualityPair { 98 public: PeerVideoQualityPairPeerVideoQualityPair99 PeerVideoQualityPair(Clock* capture_clock, VideoQualityAnalyzer* analyzer) 100 : matcher_({analyzer->Handler()}), 101 capture_tap_(capture_clock, &matcher_), 102 decode_tap_(capture_clock, &matcher_, 0) {} 103 VideoFrameMatcher matcher_; 104 CapturedFrameTap capture_tap_; 105 DecodedFrameTap decode_tap_; 106 }; 107 clock()108 Clock* clock() { return Clock::GetRealTimeClock(); } 109 110 std::unique_ptr<LogWriterFactoryInterface> GetLogWriterFactory( 111 std::string name); 112 113 const std::unique_ptr<LogWriterFactoryInterface> log_writer_manager_; 114 NetworkEmulationManagerImpl net_; 115 rtc::Thread* const signaling_thread_; 116 std::list<PeerVideoQualityPair> video_quality_pairs_; 117 std::list<PeerScenarioClient> peer_clients_; 118 }; 119 120 } // namespace test 121 } // namespace webrtc 122 #endif // TEST_PEER_SCENARIO_PEER_SCENARIO_H_ 123