/* * 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 #include #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 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 send_link, std::vector 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 send_link, std::vector 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* 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 GetLogWriterFactory( std::string name); const std::unique_ptr log_writer_manager_; NetworkEmulationManagerImpl net_; rtc::Thread* const signaling_thread_; std::list video_quality_pairs_; std::list peer_clients_; }; } // namespace test } // namespace webrtc #endif // TEST_PEER_SCENARIO_PEER_SCENARIO_H_