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:
hbos 2016-10-18 12:48:31 -07:00 committed by Commit bot
parent 1394c7b594
commit cc555c5019
6 changed files with 233 additions and 13 deletions

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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 {

View File

@ -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

View File

@ -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);