| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 | /* *  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_
 |