Fix datachannel stats id and timestamp.
Makes the id now be "datachannel_#####" where '####' is the id number for the datachannel.
Adds a timestamp to the data channel reports.
Implements unit tests to verify that the timestamp is set correctly.
BUG=1805
R=juberti@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/33119004
Cr-Commit-Position: refs/heads/master@{#8236}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8236 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/statscollector.cc b/talk/app/webrtc/statscollector.cc
index 125e52c..499df66 100644
--- a/talk/app/webrtc/statscollector.cc
+++ b/talk/app/webrtc/statscollector.cc
@@ -56,10 +56,6 @@
const char* STATSREPORT_ADAPTER_TYPE_WWAN = "wwan";
const char* STATSREPORT_ADAPTER_TYPE_VPN = "vpn";
-double GetTimeNow() {
- return rtc::Timing::WallTimeNow() * rtc::kNumMillisecsPerSec;
-}
-
bool GetTransportIdFromProxy(const cricket::ProxyTransportMap& map,
const std::string& proxy,
std::string* transport) {
@@ -379,6 +375,10 @@
ASSERT(session_->signaling_thread()->IsCurrent());
}
+double StatsCollector::GetTimeNow() {
+ return rtc::Timing::WallTimeNow() * rtc::kNumMillisecsPerSec;
+}
+
// Adds a MediaStream with tracks that can be used as a |selector| in a call
// to GetStats.
void StatsCollector::AddStream(MediaStreamInterface* stream) {
@@ -830,10 +830,10 @@
for (const auto& dc :
session_->mediastream_signaling()->sctp_data_channels()) {
- rtc::scoped_ptr<StatsReport::Id> id(
- StatsReport::NewTypedId(StatsReport::kStatsReportTypeDataChannel,
- dc->label()));
+ rtc::scoped_ptr<StatsReport::Id> id(StatsReport::NewTypedIntId(
+ StatsReport::kStatsReportTypeDataChannel, dc->id()));
StatsReport* report = reports_.ReplaceOrAddNew(id.Pass());
+ report->set_timestamp(stats_gathering_started_);
report->AddValue(StatsReport::kStatsValueNameLabel, dc->label());
report->AddValue(StatsReport::kStatsValueNameDataChannelId, dc->id());
report->AddValue(StatsReport::kStatsValueNameProtocol, dc->protocol());
diff --git a/talk/app/webrtc/statscollector.h b/talk/app/webrtc/statscollector.h
index 499da44..a4e42c9 100644
--- a/talk/app/webrtc/statscollector.h
+++ b/talk/app/webrtc/statscollector.h
@@ -97,6 +97,9 @@
private:
friend class StatsCollectorTest;
+ // Overridden in unit tests to fake timing.
+ virtual double GetTimeNow();
+
bool CopySelectedReports(const std::string& selector, StatsReports* reports);
// Helper method for AddCertificateReports.
diff --git a/talk/app/webrtc/statscollector_unittest.cc b/talk/app/webrtc/statscollector_unittest.cc
index b8c983b..96975c2 100644
--- a/talk/app/webrtc/statscollector_unittest.cc
+++ b/talk/app/webrtc/statscollector_unittest.cc
@@ -455,6 +455,20 @@
voice_receiver_info->expand_rate = 121;
}
+class StatsCollectorForTest : public webrtc::StatsCollector {
+ public:
+ explicit StatsCollectorForTest(WebRtcSession* session) :
+ StatsCollector(session), time_now_(19477) {
+ }
+
+ double GetTimeNow() override {
+ return time_now_;
+ }
+
+ private:
+ double time_now_;
+};
+
class StatsCollectorTest : public testing::Test {
protected:
StatsCollectorTest()
@@ -615,7 +629,7 @@
const std::vector<std::string>& local_ders,
const rtc::FakeSSLCertificate& remote_cert,
const std::vector<std::string>& remote_ders) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
@@ -718,12 +732,22 @@
config.id = id;
signaling_.AddDataChannel(DataChannel::Create(
&data_channel_provider_, cricket::DCT_SCTP, label, config));
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
StatsReports reports;
stats.GetStats(NULL, &reports);
+
+ const StatsReport* report =
+ FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1);
+
+ scoped_ptr<StatsReport::Id> reportId = StatsReport::NewTypedIntId(
+ StatsReport::kStatsReportTypeDataChannel, id);
+
+ EXPECT_TRUE(reportId->Equals(report->id()));
+
+ EXPECT_EQ(stats.GetTimeNow(), report->timestamp());
EXPECT_EQ(label, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel,
reports,
StatsReport::kStatsValueNameLabel));
@@ -741,7 +765,7 @@
// This test verifies that 64-bit counters are passed successfully.
TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
cricket::VideoChannel video_channel(rtc::Thread::Current(),
@@ -775,7 +799,7 @@
// Test that BWE information is reported via stats.
TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
cricket::VideoChannel video_channel(rtc::Thread::Current(),
@@ -820,7 +844,7 @@
// This test verifies that an object of type "googSession" always
// exists in the returned stats.
TEST_F(StatsCollectorTest, SessionObjectExists) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
@@ -835,7 +859,7 @@
// This test verifies that only one object of type "googSession" exists
// in the returned stats.
TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
@@ -854,7 +878,7 @@
// This test verifies that the empty track report exists in the returned stats
// without calling StatsCollector::UpdateStats.
TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
cricket::VideoChannel video_channel(rtc::Thread::Current(),
@@ -878,7 +902,7 @@
// This test verifies that the empty track report exists in the returned stats
// when StatsCollector::UpdateStats is called with ssrc stats.
TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
cricket::VideoChannel video_channel(rtc::Thread::Current(),
@@ -934,7 +958,7 @@
// This test verifies that an SSRC object has the identifier of a Transport
// stats object, and that this transport stats object exists in stats.
TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
// Ignore unused callback (logspam).
EXPECT_CALL(session_, GetTransport(_))
@@ -995,7 +1019,7 @@
// This test verifies that a remote stats object will not be created for
// an outgoing SSRC where remote stats are not returned.
TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
// The content_name known by the video channel.
@@ -1019,7 +1043,7 @@
// This test verifies that a remote stats object will be created for
// an outgoing SSRC where stats are returned.
TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
// Ignore unused callback (logspam).
EXPECT_CALL(session_, GetTransport(_))
@@ -1062,13 +1086,13 @@
const StatsReport* remote_report = FindNthReportByType(reports,
StatsReport::kStatsReportTypeRemoteSsrc, 1);
EXPECT_FALSE(remote_report == NULL);
- EXPECT_NE(0, remote_report->timestamp());
+ EXPECT_EQ(12345.678, remote_report->timestamp());
}
// This test verifies that the empty track report exists in the returned stats
// when StatsCollector::UpdateStats is called with ssrc stats.
TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
cricket::VideoChannel video_channel(rtc::Thread::Current(),
@@ -1114,7 +1138,7 @@
// This test verifies the Ice Candidate report should contain the correct
// information from local/remote candidates.
TEST_F(StatsCollectorTest, IceCandidateReport) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
@@ -1244,7 +1268,7 @@
// This test verifies that the stats are generated correctly when no
// transport is present.
TEST_F(StatsCollectorTest, NoTransport) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
@@ -1291,7 +1315,7 @@
// This test verifies that the stats are generated correctly when the transport
// does not have any certificates.
TEST_F(StatsCollectorTest, NoCertificates) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
StatsReports reports; // returned values.
@@ -1360,7 +1384,7 @@
// Verifies the correct optons are passed to the VideoMediaChannel when using
// verbose output level.
TEST_F(StatsCollectorTest, StatsOutputLevelVerbose) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
cricket::VideoChannel video_channel(rtc::Thread::Current(),
@@ -1406,7 +1430,7 @@
// This test verifies that a local stats object can get statistics via
// AudioTrackInterface::GetStats() method.
TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
// Ignore unused callback (logspam).
EXPECT_CALL(session_, GetTransport(_))
@@ -1440,7 +1464,7 @@
// This test verifies that audio receive streams populate stats reports
// correctly.
TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
// Ignore unused callback (logspam).
EXPECT_CALL(session_, GetTransport(_))
@@ -1467,7 +1491,7 @@
// This test verifies that a local stats object won't update its statistics
// after a RemoveLocalAudioTrack() call.
TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
// Ignore unused callback (logspam).
EXPECT_CALL(session_, GetTransport(_))
@@ -1525,7 +1549,7 @@
// This test verifies that when ongoing and incoming audio tracks are using
// the same ssrc, they populate stats reports correctly.
TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
// Ignore unused callback (logspam).
EXPECT_CALL(session_, GetTransport(_))
@@ -1608,7 +1632,7 @@
// TODO(xians): Figure out if it is possible to encapsulate the setup and
// avoid duplication of code in test cases.
TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) {
- webrtc::StatsCollector stats(&session_);
+ StatsCollectorForTest stats(&session_);
// Ignore unused callback (logspam).
EXPECT_CALL(session_, GetTransport(_))
diff --git a/talk/app/webrtc/statstypes.cc b/talk/app/webrtc/statstypes.cc
index a9f30e5..31ae740 100644
--- a/talk/app/webrtc/statstypes.cc
+++ b/talk/app/webrtc/statstypes.cc
@@ -76,7 +76,6 @@
class TypedId : public StatsReport::Id {
public:
- static const char kSeparator = '_';
TypedId(StatsReport::StatsType type, const std::string& id)
: StatsReport::Id(type), id_(id) {}
@@ -93,6 +92,26 @@
const std::string id_;
};
+class TypedIntId : public StatsReport::Id {
+ public:
+ TypedIntId(StatsReport::StatsType type, int id)
+ : StatsReport::Id(type), id_(id) {}
+
+ bool Equals(const Id& other) const override {
+ return Id::Equals(other) &&
+ static_cast<const TypedIntId&>(other).id_ == id_;
+ }
+
+ std::string ToString() const override {
+ return std::string(InternalTypeToString(type_)) +
+ kSeparator +
+ rtc::ToString<int>(id_);
+ }
+
+ protected:
+ const int id_;
+};
+
class IdWithDirection : public TypedId {
public:
IdWithDirection(StatsReport::StatsType type, const std::string& id,
@@ -106,7 +125,7 @@
std::string ToString() const override {
std::string ret(TypedId::ToString());
- ret += '_';
+ ret += kSeparator;
ret += direction_ == StatsReport::kSend ? "send" : "recv";
return ret;
}
@@ -437,6 +456,11 @@
}
// static
+scoped_ptr<StatsReport::Id> StatsReport::NewTypedIntId(StatsType type, int id) {
+ return scoped_ptr<Id>(new TypedIntId(type, id)).Pass();
+}
+
+// static
scoped_ptr<StatsReport::Id> StatsReport::NewIdWithDirection(
StatsType type, const std::string& id, StatsReport::Direction direction) {
return scoped_ptr<Id>(new IdWithDirection(type, id, direction)).Pass();
diff --git a/talk/app/webrtc/statstypes.h b/talk/app/webrtc/statstypes.h
index 8f132db..a3abc2e 100644
--- a/talk/app/webrtc/statstypes.h
+++ b/talk/app/webrtc/statstypes.h
@@ -229,6 +229,8 @@
protected:
Id(StatsType type); // Only meant for derived classes.
const StatsType type_;
+
+ static const char kSeparator = '_';
};
struct Value {
@@ -254,6 +256,7 @@
// Factory functions for various types of stats IDs.
static rtc::scoped_ptr<Id> NewBandwidthEstimationId();
static rtc::scoped_ptr<Id> NewTypedId(StatsType type, const std::string& id);
+ static rtc::scoped_ptr<Id> NewTypedIntId(StatsType type, int id);
static rtc::scoped_ptr<Id> NewIdWithDirection(
StatsType type, const std::string& id, Direction direction);
static rtc::scoped_ptr<Id> NewCandidateId(bool local, const std::string& id);