[PCLF] Make it possible to unregister participant for stats poller

Bug: b/231397778
Change-Id: I54c95543cbcf7d6ec9ae0bd121a07fd4e2a1fd4c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/265408
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37169}
This commit is contained in:
Artem Titov 2022-06-09 18:04:50 +02:00 committed by WebRTC LUCI CQ
parent a976a87115
commit 5f308fdd89
7 changed files with 187 additions and 9 deletions

View File

@ -39,6 +39,7 @@ if (!build_with_chromium) {
":multi_head_queue_test",
":peer_connection_e2e_smoke_test",
":single_process_encoded_image_data_injector_unittest",
":stats_poller_test",
":video_frame_tracking_id_injector_unittest",
]
}
@ -226,6 +227,7 @@ if (!build_with_chromium) {
deps = [
":peer_configurer",
":peer_connection_quality_test_params",
":stats_provider",
"../../../api:frame_generator_api",
"../../../api:function_view",
"../../../api:libjingle_peerconnection_api",
@ -500,6 +502,13 @@ if (!build_with_chromium) {
}
}
rtc_library("stats_provider") {
visibility = [ "*" ]
testonly = true
sources = [ "stats_provider.h" ]
deps = [ "../../../api:rtc_stats_api" ]
}
rtc_library("stats_poller") {
visibility = [ "*" ]
testonly = true
@ -508,6 +517,7 @@ if (!build_with_chromium) {
"stats_poller.h",
]
deps = [
":stats_provider",
":test_peer",
"../../../api:libjingle_peerconnection_api",
"../../../api:rtc_stats_api",
@ -518,6 +528,16 @@ if (!build_with_chromium) {
]
}
rtc_library("stats_poller_test") {
testonly = true
sources = [ "stats_poller_test.cc" ]
deps = [
":stats_poller",
"../..:test_support",
"../../../api:rtc_stats_api",
]
}
rtc_library("default_video_quality_analyzer_test") {
testonly = true
sources = [ "analyzer/video/default_video_quality_analyzer_test.cc" ]

View File

@ -329,8 +329,10 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
for (auto& reporter : quality_metrics_reporters_) {
observers.push_back(reporter.get());
}
StatsPoller stats_poller(observers, {{*alice_->params().name, alice_.get()},
{*bob_->params().name, bob_.get()}});
StatsPoller stats_poller(observers,
std::map<std::string, StatsProvider*>{
{*alice_->params().name, alice_.get()},
{*bob_->params().name, bob_.get()}});
executor_->ScheduleActivity(TimeDelta::Zero(), kStatsUpdateInterval,
[&stats_poller](TimeDelta) {
stats_poller.PollStatsAndNotifyObservers();

View File

@ -19,7 +19,7 @@ namespace webrtc {
namespace webrtc_pc_e2e {
void InternalStatsObserver::PollStats() {
peer_->pc()->GetStats(this);
peer_->GetStats(this);
}
void InternalStatsObserver::OnStatsDelivered(
@ -29,9 +29,19 @@ void InternalStatsObserver::OnStatsDelivered(
}
}
StatsPoller::StatsPoller(std::vector<StatsObserverInterface*> observers,
std::map<std::string, StatsProvider*> peers)
: observers_(std::move(observers)) {
webrtc::MutexLock lock(&mutex_);
for (auto& peer : peers) {
pollers_.push_back(rtc::make_ref_counted<InternalStatsObserver>(
peer.first, peer.second, observers_));
}
}
StatsPoller::StatsPoller(std::vector<StatsObserverInterface*> observers,
std::map<std::string, TestPeer*> peers)
: observers_(observers) {
: observers_(std::move(observers)) {
webrtc::MutexLock lock(&mutex_);
for (auto& peer : peers) {
pollers_.push_back(rtc::make_ref_counted<InternalStatsObserver>(
@ -47,11 +57,22 @@ void StatsPoller::PollStatsAndNotifyObservers() {
}
void StatsPoller::RegisterParticipantInCall(absl::string_view peer_name,
TestPeer* peer) {
StatsProvider* peer) {
webrtc::MutexLock lock(&mutex_);
pollers_.push_back(rtc::make_ref_counted<InternalStatsObserver>(
peer_name, peer, observers_));
}
bool StatsPoller::UnregisterParticipantInCall(absl::string_view peer_name) {
webrtc::MutexLock lock(&mutex_);
for (auto it = pollers_.begin(); it != pollers_.end(); ++it) {
if ((*it)->pc_label() == peer_name) {
pollers_.erase(it);
return true;
}
}
return false;
}
} // namespace webrtc_pc_e2e
} // namespace webrtc

View File

@ -21,6 +21,7 @@
#include "api/test/stats_observer_interface.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"
#include "test/pc/e2e/stats_provider.h"
#include "test/pc/e2e/test_peer.h"
namespace webrtc {
@ -31,10 +32,12 @@ namespace webrtc_pc_e2e {
class InternalStatsObserver : public RTCStatsCollectorCallback {
public:
InternalStatsObserver(absl::string_view pc_label,
TestPeer* peer,
StatsProvider* peer,
std::vector<StatsObserverInterface*> observers)
: pc_label_(pc_label), peer_(peer), observers_(std::move(observers)) {}
std::string pc_label() const { return pc_label_; }
void PollStats();
void OnStatsDelivered(
@ -42,7 +45,7 @@ class InternalStatsObserver : public RTCStatsCollectorCallback {
private:
std::string pc_label_;
TestPeer* peer_;
StatsProvider* peer_;
std::vector<StatsObserverInterface*> observers_;
};
@ -51,12 +54,18 @@ class InternalStatsObserver : public RTCStatsCollectorCallback {
// webrtc::test::StatsObserverInterface subscribed.
class StatsPoller {
public:
StatsPoller(std::vector<StatsObserverInterface*> observers,
std::map<std::string, StatsProvider*> peers_to_observe);
StatsPoller(std::vector<StatsObserverInterface*> observers,
std::map<std::string, TestPeer*> peers_to_observe);
void PollStatsAndNotifyObservers();
void RegisterParticipantInCall(absl::string_view peer_name, TestPeer* peer);
void RegisterParticipantInCall(absl::string_view peer_name,
StatsProvider* peer);
// Unregister participant from stats poller. Returns true if participant was
// removed and false if participant wasn't found.
bool UnregisterParticipantInCall(absl::string_view peer_name);
private:
const std::vector<StatsObserverInterface*> observers_;

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2022 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.
*/
#include "test/pc/e2e/stats_poller.h"
#include "api/stats/rtc_stats_collector_callback.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace webrtc_pc_e2e {
namespace {
using ::testing::Eq;
class TestStatsProvider : public StatsProvider {
public:
~TestStatsProvider() override = default;
void GetStats(RTCStatsCollectorCallback* callback) override {
stats_collections_count_++;
}
int stats_collections_count() const { return stats_collections_count_; }
private:
int stats_collections_count_ = 0;
};
class MockStatsObserver : public StatsObserverInterface {
public:
~MockStatsObserver() override = default;
MOCK_METHOD(void,
OnStatsReports,
(absl::string_view pc_label,
const rtc::scoped_refptr<const RTCStatsReport>& report));
};
TEST(StatsPollerTest, UnregisterParticipantAddedInCtor) {
TestStatsProvider alice;
TestStatsProvider bob;
MockStatsObserver stats_observer;
StatsPoller poller(/*observers=*/{&stats_observer},
/*peers_to_observe=*/{{"alice", &alice}, {"bob", &bob}});
poller.PollStatsAndNotifyObservers();
EXPECT_THAT(alice.stats_collections_count(), Eq(1));
EXPECT_THAT(bob.stats_collections_count(), Eq(1));
poller.UnregisterParticipantInCall("bob");
poller.PollStatsAndNotifyObservers();
EXPECT_THAT(alice.stats_collections_count(), Eq(2));
EXPECT_THAT(bob.stats_collections_count(), Eq(1));
}
TEST(StatsPollerTest, UnregisterParticipantRegisteredInCall) {
TestStatsProvider alice;
TestStatsProvider bob;
MockStatsObserver stats_observer;
StatsPoller poller(/*observers=*/{&stats_observer},
/*peers_to_observe=*/{{"alice", &alice}});
poller.RegisterParticipantInCall("bob", &bob);
poller.PollStatsAndNotifyObservers();
EXPECT_THAT(alice.stats_collections_count(), Eq(1));
EXPECT_THAT(bob.stats_collections_count(), Eq(1));
poller.UnregisterParticipantInCall("bob");
poller.PollStatsAndNotifyObservers();
EXPECT_THAT(alice.stats_collections_count(), Eq(2));
EXPECT_THAT(bob.stats_collections_count(), Eq(1));
}
} // namespace
} // namespace webrtc_pc_e2e
} // namespace webrtc

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2022 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_PC_E2E_STATS_PROVIDER_H_
#define TEST_PC_E2E_STATS_PROVIDER_H_
#include "api/stats/rtc_stats_collector_callback.h"
namespace webrtc {
namespace webrtc_pc_e2e {
class StatsProvider {
public:
virtual ~StatsProvider() = default;
virtual void GetStats(RTCStatsCollectorCallback* callback) = 0;
};
} // namespace webrtc_pc_e2e
} // namespace webrtc
#endif // TEST_PC_E2E_STATS_PROVIDER_H_

View File

@ -28,13 +28,16 @@
#include "rtc_base/synchronization/mutex.h"
#include "test/pc/e2e/peer_configurer.h"
#include "test/pc/e2e/peer_connection_quality_test_params.h"
#include "test/pc/e2e/stats_provider.h"
namespace webrtc {
namespace webrtc_pc_e2e {
// Describes a single participant in the call.
class TestPeer final {
class TestPeer final : public StatsProvider {
public:
~TestPeer() override = default;
const Params& params() const { return params_; }
ConfigurableParams configurable_params() const;
@ -45,6 +48,10 @@ class TestPeer final {
void SetVideoSubscription(
PeerConnectionE2EQualityTestFixture::VideoSubscription subscription);
void GetStats(RTCStatsCollectorCallback* callback) override {
pc()->GetStats(callback);
}
PeerConfigurerImpl::VideoSource ReleaseVideoSource(size_t i) {
RTC_CHECK(wrapper_) << "TestPeer is already closed";
return std::move(video_sources_[i]);