RTCDataChannelStats[1] added, supporting all stats members.
Also updates MockDataChannel to also mock id, messages_sent, bytes_sent, messages_received and bytes_received. [1] https://w3c.github.io/webrtc-stats/#dcstats-dict* BUG=chromium:654927, chromium:627816 Review-Url: https://codereview.webrtc.org/2420473002 Cr-Commit-Position: refs/heads/master@{#14670}
This commit is contained in:
parent
1394c7b594
commit
cc555c5019
@ -23,6 +23,8 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* CandidateTypeToRTCIceCandidateType(const std::string& type) {
|
||||
if (type == cricket::LOCAL_PORT_TYPE)
|
||||
return RTCIceCandidateType::kHost;
|
||||
@ -36,6 +38,25 @@ const char* CandidateTypeToRTCIceCandidateType(const std::string& type) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* DataStateToRTCDataChannelState(
|
||||
DataChannelInterface::DataState state) {
|
||||
switch (state) {
|
||||
case DataChannelInterface::kConnecting:
|
||||
return RTCDataChannelState::kConnecting;
|
||||
case DataChannelInterface::kOpen:
|
||||
return RTCDataChannelState::kOpen;
|
||||
case DataChannelInterface::kClosing:
|
||||
return RTCDataChannelState::kClosing;
|
||||
case DataChannelInterface::kClosed:
|
||||
return RTCDataChannelState::kClosed;
|
||||
default:
|
||||
RTC_NOTREACHED();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
rtc::scoped_refptr<RTCStatsCollector> RTCStatsCollector::Create(
|
||||
PeerConnection* pc, int64_t cache_lifetime_us) {
|
||||
return rtc::scoped_refptr<RTCStatsCollector>(
|
||||
@ -111,6 +132,7 @@ void RTCStatsCollector::ProducePartialResultsOnSignalingThread(
|
||||
ProduceIceCandidateAndPairStats_s(timestamp_us, session_stats,
|
||||
report.get());
|
||||
}
|
||||
ProduceDataChannelStats_s(timestamp_us, report.get());
|
||||
ProducePeerConnectionStats_s(timestamp_us, report.get());
|
||||
|
||||
AddPartialResults(report);
|
||||
@ -218,6 +240,28 @@ void RTCStatsCollector::ProduceCertificateStatsFromSSLCertificateAndChain_s(
|
||||
}
|
||||
}
|
||||
|
||||
void RTCStatsCollector::ProduceDataChannelStats_s(
|
||||
int64_t timestamp_us, RTCStatsReport* report) const {
|
||||
RTC_DCHECK(signaling_thread_->IsCurrent());
|
||||
for (const rtc::scoped_refptr<DataChannel>& data_channel :
|
||||
pc_->sctp_data_channels()) {
|
||||
std::unique_ptr<RTCDataChannelStats> data_channel_stats(
|
||||
new RTCDataChannelStats(
|
||||
"RTCDataChannel_" + rtc::ToString<>(data_channel->id()),
|
||||
timestamp_us));
|
||||
data_channel_stats->label = data_channel->label();
|
||||
data_channel_stats->protocol = data_channel->protocol();
|
||||
data_channel_stats->datachannelid = data_channel->id();
|
||||
data_channel_stats->state =
|
||||
DataStateToRTCDataChannelState(data_channel->state());
|
||||
data_channel_stats->messages_sent = data_channel->messages_sent();
|
||||
data_channel_stats->bytes_sent = data_channel->bytes_sent();
|
||||
data_channel_stats->messages_received = data_channel->messages_received();
|
||||
data_channel_stats->bytes_received = data_channel->bytes_received();
|
||||
report->AddStats(std::move(data_channel_stats));
|
||||
}
|
||||
}
|
||||
|
||||
void RTCStatsCollector::ProduceIceCandidateAndPairStats_s(
|
||||
int64_t timestamp_us, const SessionStats& session_stats,
|
||||
RTCStatsReport* report) const {
|
||||
@ -337,4 +381,14 @@ void RTCStatsCollector::ProducePeerConnectionStats_s(
|
||||
report->AddStats(std::move(stats));
|
||||
}
|
||||
|
||||
const char* CandidateTypeToRTCIceCandidateTypeForTesting(
|
||||
const std::string& type) {
|
||||
return CandidateTypeToRTCIceCandidateType(type);
|
||||
}
|
||||
|
||||
const char* DataStateToRTCDataChannelStateForTesting(
|
||||
DataChannelInterface::DataState state) {
|
||||
return DataStateToRTCDataChannelState(state);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/api/datachannelinterface.h"
|
||||
#include "webrtc/api/stats/rtcstats_objects.h"
|
||||
#include "webrtc/api/stats/rtcstatsreport.h"
|
||||
#include "webrtc/base/asyncinvoker.h"
|
||||
@ -85,6 +86,9 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface {
|
||||
void ProduceCertificateStatsFromSSLCertificateAndChain_s(
|
||||
int64_t timestamp_us, const rtc::SSLCertificate& certificate,
|
||||
RTCStatsReport* report) const;
|
||||
// Produces |RTCDataChannelStats|.
|
||||
void ProduceDataChannelStats_s(
|
||||
int64_t timestamp_us, RTCStatsReport* report) const;
|
||||
// Produces |RTCIceCandidatePairStats| and |RTCIceCandidateStats|.
|
||||
void ProduceIceCandidateAndPairStats_s(
|
||||
int64_t timestamp_us, const SessionStats& session_stats,
|
||||
@ -116,8 +120,10 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface {
|
||||
rtc::scoped_refptr<const RTCStatsReport> cached_report_;
|
||||
};
|
||||
|
||||
// Helper function, exposed for unittests.
|
||||
const char* CandidateTypeToRTCIceCandidateType(const std::string& type);
|
||||
const char* CandidateTypeToRTCIceCandidateTypeForTesting(
|
||||
const std::string& type);
|
||||
const char* DataStateToRTCDataChannelStateForTesting(
|
||||
DataChannelInterface::DataState state);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -328,6 +328,10 @@ class RTCStatsCollectorTest : public testing::Test {
|
||||
rtc::scoped_refptr<StatsCallback> callback = StatsCallback::Create();
|
||||
collector_->GetStatsReport(callback);
|
||||
EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
|
||||
int64_t after = rtc::TimeUTCMicros();
|
||||
for (const RTCStats& stats : *callback->report()) {
|
||||
EXPECT_LE(stats.timestamp_us(), after);
|
||||
}
|
||||
return callback->report();
|
||||
}
|
||||
|
||||
@ -347,7 +351,7 @@ class RTCStatsCollectorTest : public testing::Test {
|
||||
static_cast<int32_t>(candidate.address().port()));
|
||||
EXPECT_EQ(*candidate_stats->protocol, candidate.protocol());
|
||||
EXPECT_EQ(*candidate_stats->candidate_type,
|
||||
CandidateTypeToRTCIceCandidateType(candidate.type()));
|
||||
CandidateTypeToRTCIceCandidateTypeForTesting(candidate.type()));
|
||||
EXPECT_EQ(*candidate_stats->priority,
|
||||
static_cast<int32_t>(candidate.priority()));
|
||||
// TODO(hbos): Define candidate_stats->url. crbug.com/632723
|
||||
@ -438,6 +442,27 @@ class RTCStatsCollectorTest : public testing::Test {
|
||||
}
|
||||
}
|
||||
|
||||
void ExpectReportContainsDataChannel(
|
||||
const rtc::scoped_refptr<const RTCStatsReport>& report,
|
||||
const DataChannel& data_channel) {
|
||||
const RTCStats* stats = report->Get("RTCDataChannel_" +
|
||||
rtc::ToString<>(data_channel.id()));
|
||||
EXPECT_TRUE(stats);
|
||||
const RTCDataChannelStats& data_channel_stats =
|
||||
stats->cast_to<const RTCDataChannelStats>();
|
||||
EXPECT_EQ(*data_channel_stats.label, data_channel.label());
|
||||
EXPECT_EQ(*data_channel_stats.protocol, data_channel.protocol());
|
||||
EXPECT_EQ(*data_channel_stats.datachannelid, data_channel.id());
|
||||
EXPECT_EQ(*data_channel_stats.state,
|
||||
DataStateToRTCDataChannelStateForTesting(data_channel.state()));
|
||||
EXPECT_EQ(*data_channel_stats.messages_sent, data_channel.messages_sent());
|
||||
EXPECT_EQ(*data_channel_stats.bytes_sent, data_channel.bytes_sent());
|
||||
EXPECT_EQ(*data_channel_stats.messages_received,
|
||||
data_channel.messages_received());
|
||||
EXPECT_EQ(*data_channel_stats.bytes_received,
|
||||
data_channel.bytes_received());
|
||||
}
|
||||
|
||||
protected:
|
||||
rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
|
||||
rtc::scoped_refptr<RTCStatsCollector> collector_;
|
||||
@ -643,6 +668,44 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
|
||||
ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(0, DataChannelInterface::kConnecting));
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(1, DataChannelInterface::kOpen));
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(2, DataChannelInterface::kClosing));
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(3, DataChannelInterface::kClosed));
|
||||
|
||||
rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
|
||||
ExpectReportContainsDataChannel(report, *test_->data_channels()[0]);
|
||||
ExpectReportContainsDataChannel(report, *test_->data_channels()[1]);
|
||||
ExpectReportContainsDataChannel(report, *test_->data_channels()[2]);
|
||||
ExpectReportContainsDataChannel(report, *test_->data_channels()[3]);
|
||||
|
||||
test_->data_channels().clear();
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(0, DataChannelInterface::kConnecting,
|
||||
1, 2, 3, 4));
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(1, DataChannelInterface::kOpen,
|
||||
5, 6, 7, 8));
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(2, DataChannelInterface::kClosing,
|
||||
9, 10, 11, 12));
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(3, DataChannelInterface::kClosed,
|
||||
13, 14, 15, 16));
|
||||
|
||||
collector_->ClearCachedStatsReport();
|
||||
report = GetStatsReport();
|
||||
ExpectReportContainsDataChannel(report, *test_->data_channels()[0]);
|
||||
ExpectReportContainsDataChannel(report, *test_->data_channels()[1]);
|
||||
ExpectReportContainsDataChannel(report, *test_->data_channels()[2]);
|
||||
ExpectReportContainsDataChannel(report, *test_->data_channels()[3]);
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
|
||||
// Candidates in the first transport stats.
|
||||
std::unique_ptr<cricket::Candidate> a_local_host = CreateFakeCandidate(
|
||||
@ -759,15 +822,11 @@ TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
|
||||
int64_t before = rtc::TimeUTCMicros();
|
||||
rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
|
||||
int64_t after = rtc::TimeUTCMicros();
|
||||
EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
|
||||
static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
|
||||
const RTCStats* stats = report->Get("RTCPeerConnection");
|
||||
EXPECT_TRUE(stats);
|
||||
EXPECT_LE(before, stats->timestamp_us());
|
||||
EXPECT_LE(stats->timestamp_us(), after);
|
||||
{
|
||||
// Expected stats with no data channels
|
||||
const RTCPeerConnectionStats& pcstats =
|
||||
@ -777,13 +836,13 @@ TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
|
||||
}
|
||||
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(DataChannelInterface::kConnecting));
|
||||
new MockDataChannel(0, DataChannelInterface::kConnecting));
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(DataChannelInterface::kOpen));
|
||||
new MockDataChannel(1, DataChannelInterface::kOpen));
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(DataChannelInterface::kClosing));
|
||||
new MockDataChannel(2, DataChannelInterface::kClosing));
|
||||
test_->data_channels().push_back(
|
||||
new MockDataChannel(DataChannelInterface::kClosed));
|
||||
new MockDataChannel(3, DataChannelInterface::kClosed));
|
||||
|
||||
collector_->ClearCachedStatsReport();
|
||||
report = GetStatsReport();
|
||||
|
||||
@ -17,6 +17,14 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// https://w3c.github.io/webrtc-pc/#idl-def-rtcdatachannelstate
|
||||
struct RTCDataChannelState {
|
||||
static const char* kConnecting;
|
||||
static const char* kOpen;
|
||||
static const char* kClosing;
|
||||
static const char* kClosed;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcstatsicecandidatepairstate
|
||||
struct RTCStatsIceCandidatePairState {
|
||||
static const char* kFrozen;
|
||||
@ -27,7 +35,7 @@ struct RTCStatsIceCandidatePairState {
|
||||
static const char* kCancelled;
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/webrtc/#rtcicecandidatetype-enum
|
||||
// https://w3c.github.io/webrtc-pc/#rtcicecandidatetype-enum
|
||||
struct RTCIceCandidateType {
|
||||
static const char* kHost;
|
||||
static const char* kSrflx;
|
||||
@ -129,6 +137,27 @@ class RTCCertificateStats final : public RTCStats {
|
||||
RTCStatsMember<std::string> issuer_certificate_id;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#dcstats-dict*
|
||||
class RTCDataChannelStats final : public RTCStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
|
||||
RTCDataChannelStats(const std::string& id, int64_t timestamp_us);
|
||||
RTCDataChannelStats(std::string&& id, int64_t timestamp_us);
|
||||
RTCDataChannelStats(const RTCDataChannelStats& other);
|
||||
~RTCDataChannelStats() override;
|
||||
|
||||
RTCStatsMember<std::string> label;
|
||||
RTCStatsMember<std::string> protocol;
|
||||
RTCStatsMember<int32_t> datachannelid;
|
||||
// TODO(hbos): Support enum types? "RTCStatsMember<RTCDataChannelState>"?
|
||||
RTCStatsMember<std::string> state;
|
||||
RTCStatsMember<uint32_t> messages_sent;
|
||||
RTCStatsMember<uint64_t> bytes_sent;
|
||||
RTCStatsMember<uint32_t> messages_received;
|
||||
RTCStatsMember<uint64_t> bytes_received;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#pcstats-dict*
|
||||
// TODO(hbos): Tracking bug crbug.com/636818
|
||||
class RTCPeerConnectionStats final : public RTCStats {
|
||||
|
||||
@ -18,12 +18,35 @@ namespace webrtc {
|
||||
|
||||
class MockDataChannel : public rtc::RefCountedObject<DataChannel> {
|
||||
public:
|
||||
explicit MockDataChannel(DataState state)
|
||||
MockDataChannel(int id, DataState state)
|
||||
: MockDataChannel(id, state, 0, 0, 0, 0) {
|
||||
}
|
||||
MockDataChannel(
|
||||
int id,
|
||||
DataState state,
|
||||
uint32_t messages_sent,
|
||||
uint64_t bytes_sent,
|
||||
uint32_t messages_received,
|
||||
uint64_t bytes_received)
|
||||
: rtc::RefCountedObject<DataChannel>(
|
||||
nullptr, cricket::DCT_NONE, "MockDataChannel") {
|
||||
EXPECT_CALL(*this, id()).WillRepeatedly(testing::Return(id));
|
||||
EXPECT_CALL(*this, state()).WillRepeatedly(testing::Return(state));
|
||||
EXPECT_CALL(*this, messages_sent()).WillRepeatedly(
|
||||
testing::Return(messages_sent));
|
||||
EXPECT_CALL(*this, bytes_sent()).WillRepeatedly(
|
||||
testing::Return(bytes_sent));
|
||||
EXPECT_CALL(*this, messages_received()).WillRepeatedly(
|
||||
testing::Return(messages_received));
|
||||
EXPECT_CALL(*this, bytes_received()).WillRepeatedly(
|
||||
testing::Return(bytes_received));
|
||||
}
|
||||
MOCK_CONST_METHOD0(id, int());
|
||||
MOCK_CONST_METHOD0(state, DataState());
|
||||
MOCK_CONST_METHOD0(messages_sent, uint32_t());
|
||||
MOCK_CONST_METHOD0(bytes_sent, uint64_t());
|
||||
MOCK_CONST_METHOD0(messages_received, uint32_t());
|
||||
MOCK_CONST_METHOD0(bytes_received, uint64_t());
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -12,6 +12,11 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const char* RTCDataChannelState::kConnecting = "connecting";
|
||||
const char* RTCDataChannelState::kOpen = "open";
|
||||
const char* RTCDataChannelState::kClosing = "closing";
|
||||
const char* RTCDataChannelState::kClosed = "closed";
|
||||
|
||||
const char* RTCStatsIceCandidatePairState::kFrozen = "frozen";
|
||||
const char* RTCStatsIceCandidatePairState::kWaiting = "waiting";
|
||||
const char* RTCStatsIceCandidatePairState::kInProgress = "inprogress";
|
||||
@ -218,6 +223,50 @@ RTCCertificateStats::RTCCertificateStats(
|
||||
RTCCertificateStats::~RTCCertificateStats() {
|
||||
}
|
||||
|
||||
WEBRTC_RTCSTATS_IMPL(RTCDataChannelStats, RTCStats, "data-channel",
|
||||
&label,
|
||||
&protocol,
|
||||
&datachannelid,
|
||||
&state,
|
||||
&messages_sent,
|
||||
&bytes_sent,
|
||||
&messages_received,
|
||||
&bytes_received);
|
||||
|
||||
RTCDataChannelStats::RTCDataChannelStats(
|
||||
const std::string& id, int64_t timestamp_us)
|
||||
: RTCDataChannelStats(std::string(id), timestamp_us) {
|
||||
}
|
||||
|
||||
RTCDataChannelStats::RTCDataChannelStats(
|
||||
std::string&& id, int64_t timestamp_us)
|
||||
: RTCStats(std::move(id), timestamp_us),
|
||||
label("label"),
|
||||
protocol("protocol"),
|
||||
datachannelid("datachannelid"),
|
||||
state("state"),
|
||||
messages_sent("messagesSent"),
|
||||
bytes_sent("bytesSent"),
|
||||
messages_received("messagesReceived"),
|
||||
bytes_received("bytesReceived") {
|
||||
}
|
||||
|
||||
RTCDataChannelStats::RTCDataChannelStats(
|
||||
const RTCDataChannelStats& other)
|
||||
: RTCStats(other.id(), other.timestamp_us()),
|
||||
label(other.label),
|
||||
protocol(other.protocol),
|
||||
datachannelid(other.datachannelid),
|
||||
state(other.state),
|
||||
messages_sent(other.messages_sent),
|
||||
bytes_sent(other.bytes_sent),
|
||||
messages_received(other.messages_received),
|
||||
bytes_received(other.bytes_received) {
|
||||
}
|
||||
|
||||
RTCDataChannelStats::~RTCDataChannelStats() {
|
||||
}
|
||||
|
||||
WEBRTC_RTCSTATS_IMPL(RTCPeerConnectionStats, RTCStats, "peer-connection",
|
||||
&data_channels_opened,
|
||||
&data_channels_closed);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user