|  | /* | 
|  | *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  | #ifndef TEST_PEER_SCENARIO_PEER_SCENARIO_H_ | 
|  | #define TEST_PEER_SCENARIO_PEER_SCENARIO_H_ | 
|  |  | 
|  | // The peer connection scenario test framework enables writing end to end unit | 
|  | // tests on the peer connection level. It's similar to the Scenario test but | 
|  | // uses the full stack, including SDP and ICE negotiation. This ensures that | 
|  | // features work end to end. It's also diffferent from the other tests on peer | 
|  | // connection level in that it does not rely on any mocks or fakes other than | 
|  | // for media input and networking. Additionally it provides direct access to the | 
|  | // underlying peer connection class. | 
|  |  | 
|  | #include <list> | 
|  | #include <vector> | 
|  |  | 
|  | #include "api/test/time_controller.h" | 
|  | #include "test/gtest.h" | 
|  | #include "test/logging/log_writer.h" | 
|  | #include "test/network/network_emulation_manager.h" | 
|  | #include "test/peer_scenario/peer_scenario_client.h" | 
|  | #include "test/peer_scenario/signaling_route.h" | 
|  | #include "test/scenario/stats_collection.h" | 
|  | #include "test/scenario/video_frame_matcher.h" | 
|  |  | 
|  | namespace webrtc { | 
|  | namespace test { | 
|  | // The PeerScenario class represents a PeerConnection simulation scenario. The | 
|  | // main purpose is to maintain ownership and ensure safe destruction order of | 
|  | // clients and network emulation. Additionally it reduces the amount of boiler | 
|  | // plate requited for some actions. For example usage see the existing tests | 
|  | // using this class. Note that it should be used from a single calling thread. | 
|  | // This thread will also be assigned as the signaling thread for all peer | 
|  | // connections that are created. This means that the process methods must be | 
|  | // used when waiting to ensure that messages are processed on the signaling | 
|  | // thread. | 
|  | class PeerScenario { | 
|  | public: | 
|  | // The name is used for log output when those are enabled by the --peer_logs | 
|  | // command line flag. Optionally, the TestInfo struct available in gtest can | 
|  | // be used to automatically generate a path based on the test name. | 
|  | explicit PeerScenario(const testing::TestInfo& test_info, | 
|  | TimeMode mode = TimeMode::kSimulated); | 
|  | explicit PeerScenario(std::string file_name, | 
|  | TimeMode mode = TimeMode::kSimulated); | 
|  | explicit PeerScenario( | 
|  | std::unique_ptr<LogWriterFactoryInterface> log_writer_manager, | 
|  | TimeMode mode = TimeMode::kSimulated); | 
|  |  | 
|  | NetworkEmulationManagerImpl* net() { return &net_; } | 
|  |  | 
|  | // Creates a client wrapping a peer connection conforming to the given config. | 
|  | // The client  will share the signaling thread with the scenario. To maintain | 
|  | // control of destruction order, ownership is kept within the scenario. | 
|  | PeerScenarioClient* CreateClient(PeerScenarioClient::Config config); | 
|  | PeerScenarioClient* CreateClient(std::string name, | 
|  | PeerScenarioClient::Config config); | 
|  |  | 
|  | // Sets up a signaling route that can be used for SDP and ICE. | 
|  | SignalingRoute ConnectSignaling(PeerScenarioClient* caller, | 
|  | PeerScenarioClient* callee, | 
|  | std::vector<EmulatedNetworkNode*> send_link, | 
|  | std::vector<EmulatedNetworkNode*> ret_link); | 
|  |  | 
|  | // Connects two clients over given links. This will also start ICE signaling | 
|  | // and SDP negotiation with default behavior. For customized behavior, | 
|  | // ConnectSignaling should be used to allow more detailed control, for | 
|  | // instance to allow different signaling and media routes. | 
|  | void SimpleConnection(PeerScenarioClient* caller, | 
|  | PeerScenarioClient* callee, | 
|  | std::vector<EmulatedNetworkNode*> send_link, | 
|  | std::vector<EmulatedNetworkNode*> ret_link); | 
|  |  | 
|  | // Starts feeding the results of comparing captured frames from |send_track| | 
|  | // with decoded frames on |receiver| to |analyzer|. | 
|  | // TODO(srte): Provide a way to detach to allow removal of tracks. | 
|  | void AttachVideoQualityAnalyzer(VideoQualityAnalyzer* analyzer, | 
|  | VideoTrackInterface* send_track, | 
|  | PeerScenarioClient* receiver); | 
|  |  | 
|  | // Waits on |event| while processing messages on the signaling thread. | 
|  | bool WaitAndProcess(std::atomic<bool>* event, | 
|  | TimeDelta max_duration = TimeDelta::Seconds(5)); | 
|  |  | 
|  | // Process messages on the signaling thread for the given duration. | 
|  | void ProcessMessages(TimeDelta duration); | 
|  |  | 
|  | private: | 
|  | // Helper struct to maintain ownership of the matcher and taps. | 
|  | struct PeerVideoQualityPair { | 
|  | public: | 
|  | PeerVideoQualityPair(Clock* capture_clock, VideoQualityAnalyzer* analyzer) | 
|  | : matcher_({analyzer->Handler()}), | 
|  | capture_tap_(capture_clock, &matcher_), | 
|  | decode_tap_(capture_clock, &matcher_, 0) {} | 
|  | VideoFrameMatcher matcher_; | 
|  | CapturedFrameTap capture_tap_; | 
|  | DecodedFrameTap decode_tap_; | 
|  | }; | 
|  |  | 
|  | Clock* clock() { return Clock::GetRealTimeClock(); } | 
|  |  | 
|  | std::unique_ptr<LogWriterFactoryInterface> GetLogWriterFactory( | 
|  | std::string name); | 
|  |  | 
|  | const std::unique_ptr<LogWriterFactoryInterface> log_writer_manager_; | 
|  | NetworkEmulationManagerImpl net_; | 
|  | rtc::Thread* const signaling_thread_; | 
|  | std::list<PeerVideoQualityPair> video_quality_pairs_; | 
|  | std::list<PeerScenarioClient> peer_clients_; | 
|  | }; | 
|  |  | 
|  | }  // namespace test | 
|  | }  // namespace webrtc | 
|  | #endif  // TEST_PEER_SCENARIO_PEER_SCENARIO_H_ |