diff --git a/api/stats/rtcstatsreport.h b/api/stats/rtcstatsreport.h index 1b32d5b7c8..a70a9ff9c1 100644 --- a/api/stats/rtcstatsreport.h +++ b/api/stats/rtcstatsreport.h @@ -67,6 +67,19 @@ class RTC_EXPORT RTCStatsReport : public rtc::RefCountInterface { const RTCStats* Get(const std::string& id) const; size_t size() const { return stats_.size(); } + // Gets the stat object of type |T| by ID, where |T| is any class descending + // from |RTCStats|. + // Returns null if there is no stats object for the given ID or it is the + // wrong type. + template + const T* GetAs(const std::string& id) const { + const RTCStats* stats = Get(id); + if (!stats || stats->type() != T::kType) { + return nullptr; + } + return &stats->cast_to(); + } + // Removes the stats object from the report, returning ownership of it or null // if there is no object with |id|. std::unique_ptr Take(const std::string& id); diff --git a/pc/peerconnection_integrationtest.cc b/pc/peerconnection_integrationtest.cc index 295006f203..dd69aebf56 100644 --- a/pc/peerconnection_integrationtest.cc +++ b/pc/peerconnection_integrationtest.cc @@ -82,6 +82,7 @@ using ::testing::UnorderedElementsAreArray; using ::testing::Return; using ::testing::SetArgPointee; using ::testing::Values; +using ::testing::UnorderedElementsAreArray; using ::testing::_; using webrtc::DataBuffer; using webrtc::DataChannelInterface; @@ -2645,7 +2646,65 @@ TEST_F(PeerConnectionIntegrationTestUnifiedPlan, EXPECT_THAT(callee_stats->TrackIds(), UnorderedElementsAreArray(track_ids)); } -// Test that we can get stats (using the new stats implemnetation) for +// Test that the new GetStats() returns stats for all outgoing/incoming streams +// with the correct track IDs if there are more than one audio and more than one +// video senders/receivers. +TEST_P(PeerConnectionIntegrationTest, NewGetStatsManyAudioAndManyVideoStreams) { + ASSERT_TRUE(CreatePeerConnectionWrappers()); + ConnectFakeSignaling(); + auto audio_sender_1 = caller()->AddAudioTrack(); + auto video_sender_1 = caller()->AddVideoTrack(); + auto audio_sender_2 = caller()->AddAudioTrack(); + auto video_sender_2 = caller()->AddVideoTrack(); + caller()->CreateAndSetAndSignalOffer(); + ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); + + MediaExpectations media_expectations; + media_expectations.CalleeExpectsSomeAudioAndVideo(); + ASSERT_TRUE_WAIT(ExpectNewFrames(media_expectations), kDefaultTimeout); + + std::vector track_ids = { + audio_sender_1->track()->id(), video_sender_1->track()->id(), + audio_sender_2->track()->id(), video_sender_2->track()->id()}; + + rtc::scoped_refptr caller_report = + caller()->NewGetStats(); + ASSERT_TRUE(caller_report); + auto outbound_stream_stats = + caller_report->GetStatsOfType(); + ASSERT_EQ(4u, outbound_stream_stats.size()); + std::vector outbound_track_ids; + for (const auto& stat : outbound_stream_stats) { + ASSERT_TRUE(stat->bytes_sent.is_defined()); + EXPECT_LT(0u, *stat->bytes_sent); + ASSERT_TRUE(stat->track_id.is_defined()); + const auto* track_stat = + caller_report->GetAs(*stat->track_id); + ASSERT_TRUE(track_stat); + outbound_track_ids.push_back(*track_stat->track_identifier); + } + EXPECT_THAT(outbound_track_ids, UnorderedElementsAreArray(track_ids)); + + rtc::scoped_refptr callee_report = + callee()->NewGetStats(); + ASSERT_TRUE(callee_report); + auto inbound_stream_stats = + callee_report->GetStatsOfType(); + ASSERT_EQ(4u, inbound_stream_stats.size()); + std::vector inbound_track_ids; + for (const auto& stat : inbound_stream_stats) { + ASSERT_TRUE(stat->bytes_received.is_defined()); + EXPECT_LT(0u, *stat->bytes_received); + ASSERT_TRUE(stat->track_id.is_defined()); + const auto* track_stat = + callee_report->GetAs(*stat->track_id); + ASSERT_TRUE(track_stat); + inbound_track_ids.push_back(*track_stat->track_identifier); + } + EXPECT_THAT(inbound_track_ids, UnorderedElementsAreArray(track_ids)); +} + +// Test that we can get stats (using the new stats implementation) for // unsignaled streams. Meaning when SSRCs/MSIDs aren't signaled explicitly in // SDP. TEST_P(PeerConnectionIntegrationTest,