From ed120ba88bb60c33aa35dda6bc164856f35f3dd2 Mon Sep 17 00:00:00 2001 From: OSSRS-AI Date: Thu, 16 Oct 2025 09:08:15 -0400 Subject: [PATCH] AI: Add utest to manually verify rtc play workflow --- trunk/src/app/srs_app_rtc_conn.cpp | 7 +- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- trunk/src/utest/srs_utest_app10.cpp | 2 +- trunk/src/utest/srs_utest_app16.cpp | 2 +- trunk/src/utest/srs_utest_app17.cpp | 4 +- trunk/src/utest/srs_utest_app6.cpp | 3 +- trunk/src/utest/srs_utest_app6.hpp | 1 + trunk/src/utest/srs_utest_app9.cpp | 4 +- trunk/src/utest/srs_utest_rtc_playstream.cpp | 445 ++++++------------- trunk/src/utest/srs_utest_rtc_playstream.hpp | 119 +---- trunk/src/utest/srs_utest_service.cpp | 30 +- trunk/src/utest/srs_utest_st2.cpp | 12 +- trunk/src/utest/srs_utest_stream_token.cpp | 4 +- 13 files changed, 185 insertions(+), 450 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 2a8b19ef2..79516167e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -454,7 +454,6 @@ SrsRtcPlayStream::SrsRtcPlayStream(ISrsExecRtcAsyncTask *exec, ISrsExpire *expir nack_enabled_ = false; nack_no_copy_ = false; - _srs_config->subscribe(this); nack_epp_ = new SrsErrorPithyPrint(); pli_worker_ = new SrsRtcPliWorker(this); @@ -473,8 +472,6 @@ SrsRtcPlayStream::~SrsRtcPlayStream() exec_->exec_rtc_async_work(new SrsRtcAsyncCallOnStop(cid_, req_)); } - _srs_config->unsubscribe(this); - srs_freep(nack_epp_); srs_freep(pli_worker_); srs_freep(trd_); @@ -496,7 +493,9 @@ SrsRtcPlayStream::~SrsRtcPlayStream() // update the statistic when client coveried. // TODO: FIXME: Should finger out the err. - stat_->on_disconnect(cid_.c_str(), srs_success); + if (stat_) { + stat_->on_disconnect(cid_.c_str(), srs_success); + } config_ = NULL; rtc_sources_ = NULL; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index a15dfbfce..d899e22a7 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -254,7 +254,7 @@ public: }; // A RTC play stream, client pull and play stream from SRS. -class SrsRtcPlayStream : public ISrsCoroutineHandler, public ISrsReloadHandler, public ISrsRtcPliWorkerHandler, public ISrsRtcSourceChangeCallback +class SrsRtcPlayStream : public ISrsCoroutineHandler, public ISrsRtcPliWorkerHandler, public ISrsRtcSourceChangeCallback { // clang-format off SRS_DECLARE_PRIVATE: // clang-format on diff --git a/trunk/src/utest/srs_utest_app10.cpp b/trunk/src/utest/srs_utest_app10.cpp index 512d880f2..db5d1a0fb 100644 --- a/trunk/src/utest/srs_utest_app10.cpp +++ b/trunk/src/utest/srs_utest_app10.cpp @@ -1874,7 +1874,7 @@ VOID TEST(SrsUtilityTest, UpdateDiskStat) SrsDiskStat first_sample = *srs_get_disk_stat(); // Wait a bit to ensure time difference - srs_usleep(100 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); // Call srs_update_disk_stat() again to calculate deltas srs_update_disk_stat(); diff --git a/trunk/src/utest/srs_utest_app16.cpp b/trunk/src/utest/srs_utest_app16.cpp index a8e936dcb..15680f8bd 100644 --- a/trunk/src/utest/srs_utest_app16.cpp +++ b/trunk/src/utest/srs_utest_app16.cpp @@ -200,7 +200,7 @@ VOID TEST(UdpListenerTest, ListenAndReceivePacket) } // Wait a bit for the listener to receive and process the packet - srs_usleep(50 * SRS_UTIME_MILLISECONDS); + srs_usleep(30 * SRS_UTIME_MILLISECONDS); // Verify that the mock handler received the packet EXPECT_TRUE(mock_handler->on_udp_packet_called_); diff --git a/trunk/src/utest/srs_utest_app17.cpp b/trunk/src/utest/srs_utest_app17.cpp index 4e4adac4f..8d24321db 100644 --- a/trunk/src/utest/srs_utest_app17.cpp +++ b/trunk/src/utest/srs_utest_app17.cpp @@ -1412,7 +1412,7 @@ VOID TEST(AppCasterFlvTest, ResourceManagerDelegation) // Verify subscription by checking that handler is notified when a resource is removed caster->remove(resource2); // Give time for async disposal (manager runs in coroutine) - srs_usleep(10 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); // Handler should have been called (but we can't easily verify this without more complex setup) // Test 14: unsubscribe() - should delegate to manager_->unsubscribe() @@ -1424,7 +1424,7 @@ VOID TEST(AppCasterFlvTest, ResourceManagerDelegation) caster->remove(resource4); // Give time for async disposal - srs_usleep(10 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); // Clean up - set to NULL to avoid double-free caster->config_ = NULL; diff --git a/trunk/src/utest/srs_utest_app6.cpp b/trunk/src/utest/srs_utest_app6.cpp index 80eb402c7..e674a0677 100644 --- a/trunk/src/utest/srs_utest_app6.cpp +++ b/trunk/src/utest/srs_utest_app6.cpp @@ -2381,6 +2381,7 @@ MockAppConfig::MockAppConfig() api_as_candidates_ = true; resolve_api_domain_ = true; keep_api_domain_ = false; + mw_msgs_ = 8; } MockAppConfig::~MockAppConfig() @@ -2446,7 +2447,7 @@ bool MockAppConfig::get_realtime_enabled(std::string vhost, bool is_rtc) int MockAppConfig::get_mw_msgs(std::string vhost, bool is_realtime, bool is_rtc) { - return 8; + return mw_msgs_; } int MockAppConfig::get_rtc_drop_for_pt(std::string vhost) diff --git a/trunk/src/utest/srs_utest_app6.hpp b/trunk/src/utest/srs_utest_app6.hpp index 37d884ee3..0a0ca0caa 100644 --- a/trunk/src/utest/srs_utest_app6.hpp +++ b/trunk/src/utest/srs_utest_app6.hpp @@ -326,6 +326,7 @@ public: bool api_as_candidates_; bool resolve_api_domain_; bool keep_api_domain_; + int mw_msgs_; public: MockAppConfig(); diff --git a/trunk/src/utest/srs_utest_app9.cpp b/trunk/src/utest/srs_utest_app9.cpp index ed07eaf6c..2c8f8bfac 100644 --- a/trunk/src/utest/srs_utest_app9.cpp +++ b/trunk/src/utest/srs_utest_app9.cpp @@ -2335,7 +2335,7 @@ VOID TEST(AppOriginHubTest, CreateForwardersTypicalScenario) } // Give coroutines time to stop - srs_usleep(10 * 1000); // 10ms + srs_usleep(1 * SRS_UTIME_MILLISECONDS); } // Hub is destroyed here, before mock_config @@ -2881,7 +2881,7 @@ VOID TEST(AppOriginHubTest, CreateBackendForwardersTypicalScenario) } // Give coroutines time to stop - srs_usleep(10 * 1000); // 10ms + srs_usleep(1 * SRS_UTIME_MILLISECONDS); } // Hub is destroyed here, before mock objects diff --git a/trunk/src/utest/srs_utest_rtc_playstream.cpp b/trunk/src/utest/srs_utest_rtc_playstream.cpp index b4f7f3fb3..27d4fde67 100644 --- a/trunk/src/utest/srs_utest_rtc_playstream.cpp +++ b/trunk/src/utest/srs_utest_rtc_playstream.cpp @@ -7,354 +7,177 @@ #include #include +#include #include #include #include -// Mock ISrsCoroutine implementation -MockCoroutineForPlayStream::MockCoroutineForPlayStream() +// MockRtcTrackDescriptionFactory implementation +MockRtcTrackDescriptionFactory::MockRtcTrackDescriptionFactory() { - start_error_ = srs_success; - start_count_ = 0; - stop_count_ = 0; - interrupt_count_ = 0; + audio_ssrc_ = 12345; + video_ssrc_ = 67890; } -MockCoroutineForPlayStream::~MockCoroutineForPlayStream() +MockRtcTrackDescriptionFactory::~MockRtcTrackDescriptionFactory() { - srs_freep(start_error_); } -srs_error_t MockCoroutineForPlayStream::start() +std::map MockRtcTrackDescriptionFactory::create_audio_video_tracks() { - start_count_++; - if (start_error_ != srs_success) { - return srs_error_copy(start_error_); - } - return srs_success; + std::map sub_relations; + + // Create audio track + SrsRtcTrackDescription *audio_desc = create_audio_track(audio_ssrc_, "audio-track-1"); + sub_relations[audio_desc->ssrc_] = audio_desc; + + // Create video track + SrsRtcTrackDescription *video_desc = create_video_track(video_ssrc_, "video-track-1"); + sub_relations[video_desc->ssrc_] = video_desc; + + return sub_relations; } -void MockCoroutineForPlayStream::stop() +SrsRtcTrackDescription *MockRtcTrackDescriptionFactory::create_audio_track(uint32_t ssrc, std::string id) { - stop_count_++; + SrsRtcTrackDescription *audio_desc = new SrsRtcTrackDescription(); + audio_desc->type_ = "audio"; + audio_desc->ssrc_ = ssrc; + audio_desc->id_ = id; + audio_desc->is_active_ = true; + audio_desc->direction_ = "sendrecv"; + audio_desc->mid_ = "0"; + audio_desc->media_ = new SrsAudioPayload(111, "opus", 48000, 2); + return audio_desc; } -void MockCoroutineForPlayStream::interrupt() +SrsRtcTrackDescription *MockRtcTrackDescriptionFactory::create_video_track(uint32_t ssrc, std::string id) { - interrupt_count_++; -} - -srs_error_t MockCoroutineForPlayStream::pull() -{ - return srs_success; -} - -const SrsContextId &MockCoroutineForPlayStream::cid() -{ - return cid_; -} - -void MockCoroutineForPlayStream::set_cid(const SrsContextId &cid) -{ - cid_ = cid; -} - -void MockCoroutineForPlayStream::reset() -{ - srs_freep(start_error_); - start_count_ = 0; - stop_count_ = 0; - interrupt_count_ = 0; -} - -void MockCoroutineForPlayStream::set_start_error(srs_error_t err) -{ - srs_freep(start_error_); - start_error_ = srs_error_copy(err); -} - -// Mock ISrsAppFactory implementation -MockAppFactoryForPlayStream::MockAppFactoryForPlayStream() -{ - mock_coroutine_ = new MockCoroutineForPlayStream(); - create_coroutine_error_ = srs_success; - create_coroutine_count_ = 0; - last_coroutine_handler_ = NULL; -} - -MockAppFactoryForPlayStream::~MockAppFactoryForPlayStream() -{ - srs_freep(mock_coroutine_); - srs_freep(create_coroutine_error_); -} - -ISrsFileWriter *MockAppFactoryForPlayStream::create_file_writer() -{ - return NULL; -} - -ISrsFileWriter *MockAppFactoryForPlayStream::create_enc_file_writer() -{ - return NULL; -} - -ISrsFileReader *MockAppFactoryForPlayStream::create_file_reader() -{ - return NULL; -} - -SrsPath *MockAppFactoryForPlayStream::create_path() -{ - return NULL; -} - -SrsLiveSource *MockAppFactoryForPlayStream::create_live_source() -{ - return NULL; -} - -ISrsOriginHub *MockAppFactoryForPlayStream::create_origin_hub() -{ - return NULL; -} - -ISrsHourGlass *MockAppFactoryForPlayStream::create_hourglass(const std::string &name, ISrsHourGlassHandler *handler, srs_utime_t interval) -{ - return NULL; -} - -ISrsBasicRtmpClient *MockAppFactoryForPlayStream::create_rtmp_client(std::string url, srs_utime_t cto, srs_utime_t sto) -{ - return NULL; -} - -ISrsHttpClient *MockAppFactoryForPlayStream::create_http_client() -{ - return NULL; -} - -ISrsFileReader *MockAppFactoryForPlayStream::create_http_file_reader(ISrsHttpResponseReader *r) -{ - return NULL; -} - -ISrsFlvDecoder *MockAppFactoryForPlayStream::create_flv_decoder() -{ - return NULL; -} - -#ifdef SRS_RTSP -ISrsRtspSendTrack *MockAppFactoryForPlayStream::create_rtsp_audio_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc) -{ - return NULL; -} - -ISrsRtspSendTrack *MockAppFactoryForPlayStream::create_rtsp_video_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc) -{ - return NULL; -} -#endif - -ISrsFlvTransmuxer *MockAppFactoryForPlayStream::create_flv_transmuxer() -{ - return NULL; -} - -ISrsMp4Encoder *MockAppFactoryForPlayStream::create_mp4_encoder() -{ - return NULL; -} - -ISrsDvrSegmenter *MockAppFactoryForPlayStream::create_dvr_flv_segmenter() -{ - return NULL; -} - -ISrsDvrSegmenter *MockAppFactoryForPlayStream::create_dvr_mp4_segmenter() -{ - return NULL; -} - -#ifdef SRS_GB28181 -ISrsGbMediaTcpConn *MockAppFactoryForPlayStream::create_gb_media_tcp_conn() -{ - return NULL; -} - -ISrsGbSession *MockAppFactoryForPlayStream::create_gb_session() -{ - return NULL; -} -#endif - -ISrsInitMp4 *MockAppFactoryForPlayStream::create_init_mp4() -{ - return NULL; -} - -ISrsFragmentWindow *MockAppFactoryForPlayStream::create_fragment_window() -{ - return NULL; -} - -ISrsFragmentedMp4 *MockAppFactoryForPlayStream::create_fragmented_mp4() -{ - return NULL; -} - -ISrsIpListener *MockAppFactoryForPlayStream::create_tcp_listener(ISrsTcpHandler *handler) -{ - return NULL; -} - -ISrsRtcConnection *MockAppFactoryForPlayStream::create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid) -{ - return NULL; -} - -ISrsFFMPEG *MockAppFactoryForPlayStream::create_ffmpeg(std::string ffmpeg_bin) -{ - return NULL; -} - -ISrsIngesterFFMPEG *MockAppFactoryForPlayStream::create_ingester_ffmpeg() -{ - return NULL; -} - -ISrsCoroutine *MockAppFactoryForPlayStream::create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid) -{ - create_coroutine_count_++; - last_coroutine_name_ = name; - last_coroutine_handler_ = handler; - last_coroutine_cid_ = cid; - - if (create_coroutine_error_ != srs_success) { - return NULL; - } - - return mock_coroutine_; -} - -ISrsTime *MockAppFactoryForPlayStream::create_time() -{ - return NULL; -} - -ISrsConfig *MockAppFactoryForPlayStream::create_config() -{ - return NULL; -} - -ISrsCond *MockAppFactoryForPlayStream::create_cond() -{ - return NULL; -} - -void MockAppFactoryForPlayStream::reset() -{ - mock_coroutine_->reset(); - srs_freep(create_coroutine_error_); - create_coroutine_count_ = 0; - last_coroutine_name_ = ""; - last_coroutine_handler_ = NULL; -} - -void MockAppFactoryForPlayStream::set_create_coroutine_error(srs_error_t err) -{ - srs_freep(create_coroutine_error_); - create_coroutine_error_ = srs_error_copy(err); -} - -// Mock ISrsRtcPliWorker implementation -MockRtcPliWorkerForPlayStream::MockRtcPliWorkerForPlayStream() -{ - start_error_ = srs_success; - start_count_ = 0; - request_keyframe_count_ = 0; -} - -MockRtcPliWorkerForPlayStream::~MockRtcPliWorkerForPlayStream() -{ - srs_freep(start_error_); -} - -srs_error_t MockRtcPliWorkerForPlayStream::start() -{ - start_count_++; - if (start_error_ != srs_success) { - return srs_error_copy(start_error_); - } - return srs_success; -} - -void MockRtcPliWorkerForPlayStream::request_keyframe(uint32_t ssrc, SrsContextId cid) -{ - request_keyframe_count_++; -} - -srs_error_t MockRtcPliWorkerForPlayStream::cycle() -{ - return srs_success; -} - -void MockRtcPliWorkerForPlayStream::reset() -{ - srs_freep(start_error_); - start_count_ = 0; - request_keyframe_count_ = 0; -} - -void MockRtcPliWorkerForPlayStream::set_start_error(srs_error_t err) -{ - srs_freep(start_error_); - start_error_ = srs_error_copy(err); + SrsRtcTrackDescription *video_desc = new SrsRtcTrackDescription(); + video_desc->type_ = "video"; + video_desc->ssrc_ = ssrc; + video_desc->id_ = id; + video_desc->is_active_ = true; + video_desc->direction_ = "sendrecv"; + video_desc->mid_ = "1"; + video_desc->media_ = new SrsVideoPayload(96, "H264", 90000); + return video_desc; } // Test SrsRtcPlayStream::start() - Basic success scenario -VOID TEST(RtcPlayStreamStartTest, StartSuccess) +VOID TEST(RtcPlayStreamTest, ManuallyVerifyBasicWorkflow) { srs_error_t err; - // Create mock objects + // Create mock objects for dependencies + MockAppConfig mock_config; + MockRtcSourceManager mock_rtc_sources; + MockRtcStatistic mock_stat; + MockRtcAsyncCallRequest mock_request("test.vhost", "live", "stream1"); MockRtcAsyncTaskExecutor mock_exec; MockExpire mock_expire; MockRtcPacketSender mock_sender; + MockRtcTrackDescriptionFactory track_factory; SrsContextId cid; cid.set_value("test-play-stream-start-cid"); - // Create RTC play stream + // Create RTC play stream - uses real app_factory_ and real pli_worker_ SrsUniquePtr play_stream(new SrsRtcPlayStream(&mock_exec, &mock_expire, &mock_sender, cid)); - // Create and inject mock app factory - MockAppFactoryForPlayStream mock_factory; - play_stream->app_factory_ = &mock_factory; + // Mock the play stream object. + if (true) { + // Inject mock dependencies + play_stream->config_ = &mock_config; + play_stream->rtc_sources_ = &mock_rtc_sources; + play_stream->stat_ = &mock_stat; - // Create and inject mock PLI worker - MockRtcPliWorkerForPlayStream *mock_pli_worker = new MockRtcPliWorkerForPlayStream(); - play_stream->pli_worker_ = mock_pli_worker; + // Set mw_msgs to 0 to make the consumer block until we push a packet + mock_config.mw_msgs_ = 0; + } - // Test: First call to start() should succeed - HELPER_EXPECT_SUCCESS(play_stream->start()); + // Create track descriptions using factory + if (true) { + std::map sub_relations = track_factory.create_audio_video_tracks(); - // Verify coroutine was created with correct parameters - EXPECT_EQ(1, mock_factory.create_coroutine_count_); - EXPECT_STREQ("rtc_sender", mock_factory.last_coroutine_name_.c_str()); - EXPECT_TRUE(mock_factory.last_coroutine_handler_ == play_stream.get()); - EXPECT_EQ(0, cid.compare(mock_factory.last_coroutine_cid_)); + // Initialize the play stream (it will take ownership of track descriptions) + HELPER_EXPECT_SUCCESS(play_stream->initialize(&mock_request, sub_relations)); - // Verify coroutine start was called - EXPECT_EQ(1, mock_factory.mock_coroutine_->start_count_); + // Test: First call to start() should succeed + HELPER_EXPECT_SUCCESS(play_stream->start()); - // Verify PLI worker start was called - EXPECT_EQ(1, mock_pli_worker->start_count_); + // Verify is_started_ flag is set + EXPECT_TRUE(play_stream->is_started_); - // Verify is_started_ flag is set - EXPECT_TRUE(play_stream->is_started_); + // Wait for coroutine to start and create consumer. Normally it should be ready + // and stopped at wait for RTP packets from consumer. + srs_usleep(1 * SRS_UTIME_MILLISECONDS); + } + + // Push a video packet to the source to feed the consumer. + if (true) { + SrsUniquePtr test_pkt(new SrsRtpPacket()); + test_pkt->frame_type_ = SrsFrameTypeVideo; + test_pkt->header_.set_sequence(1000); + test_pkt->header_.set_timestamp(5000); + test_pkt->header_.set_ssrc(track_factory.video_ssrc_); + + // Push packet to source - this will feed all consumers including the play stream's consumer + HELPER_EXPECT_SUCCESS(play_stream->source_->on_rtp(test_pkt.get())); + } + + // Verify the video packet is sent out + if (true) { + // Wait for coroutine to process the packet + srs_usleep(1 * SRS_UTIME_MILLISECONDS); + + // Check sender should have received the packet + EXPECT_EQ(mock_sender.send_packet_count_, 1); + // Check the tracks, should be a video track. + EXPECT_EQ(play_stream->video_tracks_.size(), 1); + // The packet should create a cached track for this ssrc. + EXPECT_EQ(play_stream->cache_ssrc0_, track_factory.video_ssrc_); + EXPECT_TRUE(play_stream->cache_track0_ != NULL); + // The packet should be in the nack ring buffer. + SrsRtpPacket *pkt = play_stream->cache_track0_->rtp_queue_->at(1000); + EXPECT_TRUE(pkt != NULL); + EXPECT_EQ(pkt->header_.get_ssrc(), track_factory.video_ssrc_); + } + + // Push a audio packet to the source to feed the consumer. + if (true) { + SrsUniquePtr test_pkt(new SrsRtpPacket()); + test_pkt->frame_type_ = SrsFrameTypeAudio; + test_pkt->header_.set_sequence(1000); + test_pkt->header_.set_timestamp(5000); + test_pkt->header_.set_ssrc(track_factory.audio_ssrc_); + + // Push packet to source - this will feed all consumers including the play stream's consumer + HELPER_EXPECT_SUCCESS(play_stream->source_->on_rtp(test_pkt.get())); + } + + // Verify the audio packet is sent out + if (true) { + // Wait for coroutine to process the packet + srs_usleep(1 * SRS_UTIME_MILLISECONDS); + + // Check sender should have received the packet + EXPECT_EQ(mock_sender.send_packet_count_, 2); + // Check the tracks, should be a video track. + EXPECT_EQ(play_stream->audio_tracks_.size(), 1); + // The packet should create a cached track for this ssrc. + EXPECT_EQ(play_stream->cache_ssrc1_, track_factory.audio_ssrc_); + EXPECT_TRUE(play_stream->cache_track1_ != NULL); + // The packet should be in the nack ring buffer. + SrsRtpPacket *pkt = play_stream->cache_track1_->rtp_queue_->at(1000); + EXPECT_TRUE(pkt != NULL); + EXPECT_EQ(pkt->header_.get_ssrc(), track_factory.audio_ssrc_); + } + + // Stop the play stream + play_stream->stop(); // Clean up - set to NULL to avoid double-free - play_stream->trd_ = NULL; // Set to NULL before mock_factory is destroyed - play_stream->app_factory_ = NULL; - play_stream->pli_worker_ = NULL; - srs_freep(mock_pli_worker); + play_stream->config_ = NULL; + play_stream->rtc_sources_ = NULL; + play_stream->stat_ = NULL; } diff --git a/trunk/src/utest/srs_utest_rtc_playstream.hpp b/trunk/src/utest/srs_utest_rtc_playstream.hpp index a4d81a09e..280b8fc89 100644 --- a/trunk/src/utest/srs_utest_rtc_playstream.hpp +++ b/trunk/src/utest/srs_utest_rtc_playstream.hpp @@ -7,121 +7,32 @@ #ifndef SRS_UTEST_RTC_PLAYSTREAM_HPP #define SRS_UTEST_RTC_PLAYSTREAM_HPP -/* -#include -*/ #include +#include -#include -#include -#include +class SrsRtcTrackDescription; -// Mock ISrsCoroutine for testing SrsRtcPlayStream::start() -class MockCoroutineForPlayStream : public ISrsCoroutine +// Helper class to create mock track descriptions for testing +class MockRtcTrackDescriptionFactory { public: - srs_error_t start_error_; - int start_count_; - int stop_count_; - int interrupt_count_; - SrsContextId cid_; + MockRtcTrackDescriptionFactory(); + virtual ~MockRtcTrackDescriptionFactory(); public: - MockCoroutineForPlayStream(); - virtual ~MockCoroutineForPlayStream(); + // Default SSRCs for audio and video tracks + uint32_t audio_ssrc_; + uint32_t video_ssrc_; public: - virtual srs_error_t start(); - virtual void stop(); - virtual void interrupt(); - virtual srs_error_t pull(); - virtual const SrsContextId &cid(); - virtual void set_cid(const SrsContextId &cid); + // Create a map of track descriptions with audio and video tracks + std::map create_audio_video_tracks(); -public: - void reset(); - void set_start_error(srs_error_t err); -}; + // Create a single audio track description + SrsRtcTrackDescription *create_audio_track(uint32_t ssrc, std::string id); -// Mock ISrsAppFactory for testing SrsRtcPlayStream::start() -class MockAppFactoryForPlayStream : public ISrsAppFactory -{ -public: - MockCoroutineForPlayStream *mock_coroutine_; - srs_error_t create_coroutine_error_; - int create_coroutine_count_; - std::string last_coroutine_name_; - ISrsCoroutineHandler *last_coroutine_handler_; - SrsContextId last_coroutine_cid_; - -public: - MockAppFactoryForPlayStream(); - virtual ~MockAppFactoryForPlayStream(); - -public: - // ISrsAppFactory interface methods - virtual ISrsFileWriter *create_file_writer(); - virtual ISrsFileWriter *create_enc_file_writer(); - virtual ISrsFileReader *create_file_reader(); - virtual SrsPath *create_path(); - virtual SrsLiveSource *create_live_source(); - virtual ISrsOriginHub *create_origin_hub(); - virtual ISrsHourGlass *create_hourglass(const std::string &name, ISrsHourGlassHandler *handler, srs_utime_t interval); - virtual ISrsBasicRtmpClient *create_rtmp_client(std::string url, srs_utime_t cto, srs_utime_t sto); - virtual ISrsHttpClient *create_http_client(); - virtual ISrsFileReader *create_http_file_reader(ISrsHttpResponseReader *r); - virtual ISrsFlvDecoder *create_flv_decoder(); -#ifdef SRS_RTSP - virtual ISrsRtspSendTrack *create_rtsp_audio_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc); - virtual ISrsRtspSendTrack *create_rtsp_video_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc); -#endif - virtual ISrsFlvTransmuxer *create_flv_transmuxer(); - virtual ISrsMp4Encoder *create_mp4_encoder(); - virtual ISrsDvrSegmenter *create_dvr_flv_segmenter(); - virtual ISrsDvrSegmenter *create_dvr_mp4_segmenter(); -#ifdef SRS_GB28181 - virtual ISrsGbMediaTcpConn *create_gb_media_tcp_conn(); - virtual ISrsGbSession *create_gb_session(); -#endif - virtual ISrsInitMp4 *create_init_mp4(); - virtual ISrsFragmentWindow *create_fragment_window(); - virtual ISrsFragmentedMp4 *create_fragmented_mp4(); - virtual ISrsIpListener *create_tcp_listener(ISrsTcpHandler *handler); - virtual ISrsRtcConnection *create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid); - virtual ISrsFFMPEG *create_ffmpeg(std::string ffmpeg_bin); - virtual ISrsIngesterFFMPEG *create_ingester_ffmpeg(); - - // ISrsKernelFactory interface methods - virtual ISrsCoroutine *create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid); - virtual ISrsTime *create_time(); - virtual ISrsConfig *create_config(); - virtual ISrsCond *create_cond(); - -public: - void reset(); - void set_create_coroutine_error(srs_error_t err); -}; - -// Mock ISrsRtcPliWorker for testing SrsRtcPlayStream::start() -class MockRtcPliWorkerForPlayStream : public ISrsRtcPliWorker -{ -public: - srs_error_t start_error_; - int start_count_; - int request_keyframe_count_; - -public: - MockRtcPliWorkerForPlayStream(); - virtual ~MockRtcPliWorkerForPlayStream(); - -public: - virtual srs_error_t start(); - virtual void request_keyframe(uint32_t ssrc, SrsContextId cid); - virtual srs_error_t cycle(); - -public: - void reset(); - void set_start_error(srs_error_t err); + // Create a single video track description + SrsRtcTrackDescription *create_video_track(uint32_t ssrc, std::string id); }; #endif diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index 13b5b963e..e347cbf4d 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -104,7 +104,7 @@ VOID TEST(TCPServerTest, PingPong) SrsTcpClient c(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); EXPECT_TRUE(h.fd != NULL); } @@ -117,7 +117,7 @@ VOID TEST(TCPServerTest, PingPong) SrsTcpClient c(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); #ifdef SRS_OSX ASSERT_TRUE(h.fd != NULL); #endif @@ -139,7 +139,7 @@ VOID TEST(TCPServerTest, PingPong) SrsTcpClient c(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); #ifdef SRS_OSX ASSERT_TRUE(h.fd != NULL); #endif @@ -163,7 +163,7 @@ VOID TEST(TCPServerTest, PingPong) SrsTcpClient c(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); #ifdef SRS_OSX ASSERT_TRUE(h.fd != NULL); #endif @@ -198,7 +198,7 @@ VOID TEST(TCPServerTest, PingPongWithTimeout) SrsTcpClient c(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); #ifdef SRS_OSX ASSERT_TRUE(h.fd != NULL); #endif @@ -220,7 +220,7 @@ VOID TEST(TCPServerTest, PingPongWithTimeout) SrsTcpClient c(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); #ifdef SRS_OSX ASSERT_TRUE(h.fd != NULL); #endif @@ -242,7 +242,7 @@ VOID TEST(TCPServerTest, PingPongWithTimeout) SrsTcpClient c(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); #ifdef SRS_OSX ASSERT_TRUE(h.fd != NULL); #endif @@ -437,7 +437,7 @@ VOID TEST(TCPServerTest, WritevIOVC) SrsTcpClient c(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); #ifdef SRS_OSX ASSERT_TRUE(h.fd != NULL); #endif @@ -467,7 +467,7 @@ VOID TEST(TCPServerTest, WritevIOVC) SrsTcpClient c(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); #ifdef SRS_OSX ASSERT_TRUE(h.fd != NULL); #endif @@ -1000,7 +1000,7 @@ srs_error_t MockOnCycleThread::cycle() srs_error_t err = srs_success; for (;;) { - srs_usleep(10 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); srs_cond_signal(cond); // If no one waiting on the cond, directly return event signal more than one time. // If someone waiting, signal them more than one time. @@ -1029,7 +1029,7 @@ VOID TEST(TCPServerTest, ThreadCondWait) MockOnCycleThread trd; trd.trd.start(); - srs_usleep(20 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); srs_cond_wait(trd.cond); trd.trd.stop(); } @@ -1050,7 +1050,7 @@ srs_error_t MockOnCycleThread2::cycle() for (;;) { srs_mutex_lock(lock); - srs_usleep(10 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); srs_mutex_unlock(lock); srs_error_t err = trd.pull(); @@ -1077,7 +1077,7 @@ VOID TEST(TCPServerTest, ThreadMutexWait) MockOnCycleThread2 trd; trd.trd.start(); - srs_usleep(20 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); srs_mutex_lock(trd.lock); trd.trd.stop(); @@ -1579,7 +1579,7 @@ VOID TEST(ThreadCriticalTest, FailIfCloseActiveFD) SrsTcpClient c0(_srs_tmp_host, _srs_tmp_port, _srs_tmp_timeout); HELPER_EXPECT_SUCCESS(c0.connect()); - srs_usleep(30 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); EXPECT_TRUE(h.fd != NULL); MockAsyncReaderThread trd0(h.fd); @@ -1589,7 +1589,7 @@ VOID TEST(ThreadCriticalTest, FailIfCloseActiveFD) HELPER_EXPECT_SUCCESS(trd1.start()); // Wait for all threads to run. - srs_usleep(10 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); // Should fail when close, because there is 2 threads reading fd. int r0 = st_netfd_close((st_netfd_t)h.fd); diff --git a/trunk/src/utest/srs_utest_st2.cpp b/trunk/src/utest/srs_utest_st2.cpp index 7e98002c2..792d404ff 100644 --- a/trunk/src/utest/srs_utest_st2.cpp +++ b/trunk/src/utest/srs_utest_st2.cpp @@ -26,7 +26,7 @@ VOID TEST(StTest, AnonymouseSingleCoroutine) // Wait for coroutine to terminate. Otherwise, it will be stopped // and terminated, which cause some of the code not executed. - srs_usleep(50 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); } VOID TEST(StTest, AnonymouseMultipleCoroutines) @@ -42,7 +42,7 @@ VOID TEST(StTest, AnonymouseMultipleCoroutines) // Wait for coroutine to terminate. Otherwise, it will be stopped // and terminated, which cause some of the code not executed. - srs_usleep(50 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); } VOID TEST(StTest, AnonymouseCoroutinePull) @@ -67,7 +67,7 @@ VOID TEST(StTest, AnonymouseCoroutinePull) // Wait for coroutine to run and terminated, or it will crash // because the ctx.pop is called after coroutine terminated. - srs_usleep(50 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); } EXPECT_TRUE(counter == 1); @@ -90,12 +90,12 @@ VOID TEST(StTest, AnonymouseCoroutineWithContext) // Wait for coroutine to run and terminated, or it will crash // because the ctx.pop is called after coroutine terminated. - srs_usleep(50 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); EXPECT_TRUE(counter == 1); // Wait for coroutine to terminate. Otherwise, it will be stopped // and terminated, which cause some of the code not executed. - srs_usleep(50 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); } VOID TEST(StTest, AnonymouseCoroutineWithSync) @@ -272,7 +272,7 @@ VOID TEST(StTest, AnonymouseBadcase2) // Wait for coroutine to terminate. Otherwise, it will crash, for the // coroutine is terminated while ctx.pop(), the lock is invalid. - srs_usleep(100 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); } // Coroutine terminated, so the counter is increased. diff --git a/trunk/src/utest/srs_utest_stream_token.cpp b/trunk/src/utest/srs_utest_stream_token.cpp index f1c782928..80dff3711 100644 --- a/trunk/src/utest/srs_utest_stream_token.cpp +++ b/trunk/src/utest/srs_utest_stream_token.cpp @@ -414,7 +414,7 @@ VOID TEST(StreamTokenTest, RaceConditionPrevention) } // Wait a bit for completion - srs_usleep(10 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); // Wait for all coroutines to complete for (size_t i = 0; i < threads.size(); i++) { @@ -423,7 +423,7 @@ VOID TEST(StreamTokenTest, RaceConditionPrevention) } // Wait a bit for completion - srs_usleep(10 * SRS_UTIME_MILLISECONDS); + srs_usleep(1 * SRS_UTIME_MILLISECONDS); // Check results - exactly one should succeed, others should fail int success_count = 0;