diff --git a/webrtc/api/rtcstatsreport.h b/webrtc/api/rtcstatsreport.h index 42237eba72..fbd78b93f4 100644 --- a/webrtc/api/rtcstatsreport.h +++ b/webrtc/api/rtcstatsreport.h @@ -55,9 +55,13 @@ class RTCStatsReport : public rtc::RefCountInterface { RTCStatsReport(const RTCStatsReport& other) = delete; bool AddStats(std::unique_ptr stats); - const RTCStats* operator[](const std::string& id) const; + const RTCStats* Get(const std::string& id) const; size_t size() const { return stats_.size(); } + // Takes ownership of all the stats in |victim|, leaving it empty. + void TakeMembersFrom(rtc::scoped_refptr victim); + + // Stats iterators. Stats are ordered lexicographically on |RTCStats::id|. ConstIterator begin() const; ConstIterator end() const; diff --git a/webrtc/stats/BUILD.gn b/webrtc/stats/BUILD.gn index 50f43515d4..2f69216772 100644 --- a/webrtc/stats/BUILD.gn +++ b/webrtc/stats/BUILD.gn @@ -37,6 +37,7 @@ if (rtc_include_tests) { testonly = true sources = [ "rtcstats_unittest.cc", + "rtcstatsreport_unittest.cc", ] configs += [ "..:common_config" ] diff --git a/webrtc/stats/rtcstats_unittest.cc b/webrtc/stats/rtcstats_unittest.cc index 12364aed56..44e75c41be 100644 --- a/webrtc/stats/rtcstats_unittest.cc +++ b/webrtc/stats/rtcstats_unittest.cc @@ -9,11 +9,9 @@ */ #include "webrtc/api/rtcstats.h" -#include "webrtc/api/rtcstatsreport.h" #include "webrtc/base/checks.h" #include "webrtc/base/gunit.h" -#include "webrtc/base/logging.h" namespace webrtc { @@ -165,39 +163,6 @@ TEST(RTCStatsTest, RTCStatsGrandChild) { EXPECT_EQ(*copy.grandchild_int, *stats.grandchild_int); } -TEST(RTCStatsTest, TestRTCStatsReport) { - rtc::scoped_refptr report = RTCStatsReport::Create(); - EXPECT_EQ(report->size(), static_cast(0)); - report->AddStats(std::unique_ptr(new RTCTestStats("a0", 1.0))); - report->AddStats(std::unique_ptr(new RTCTestStats("a1", 2.0))); - report->AddStats(std::unique_ptr(new RTCChildStats("b0", 4.0))); - report->AddStats(std::unique_ptr(new RTCChildStats("b1", 8.0))); - report->AddStats(std::unique_ptr(new RTCTestStats("a2", 16.0))); - report->AddStats(std::unique_ptr(new RTCChildStats("b2", 32.0))); - EXPECT_EQ(report->size(), static_cast(6)); - - EXPECT_EQ((*report)["missing"], nullptr); - EXPECT_EQ((*report)["a0"]->id(), "a0"); - EXPECT_EQ((*report)["b2"]->id(), "b2"); - - std::vector a = report->GetStatsOfType(); - EXPECT_EQ(a.size(), static_cast(3)); - uint32_t mask = 0; - for (const RTCTestStats* stats : a) - mask |= static_cast(stats->timestamp()); - EXPECT_EQ(mask, static_cast(1 | 2 | 16)); - - std::vector b = report->GetStatsOfType(); - EXPECT_EQ(b.size(), static_cast(3)); - mask = 0; - for (const RTCChildStats* stats : b) - mask |= static_cast(stats->timestamp()); - EXPECT_EQ(mask, static_cast(4 | 8 | 32)); - - EXPECT_EQ(report->GetStatsOfType().size(), - static_cast(0)); -} - // Death tests. // Disabled on Android because death tests misbehave on Android, see // base/test/gtest_util.h. diff --git a/webrtc/stats/rtcstatsreport.cc b/webrtc/stats/rtcstatsreport.cc index 870651d2df..00a55f41fc 100644 --- a/webrtc/stats/rtcstatsreport.cc +++ b/webrtc/stats/rtcstatsreport.cc @@ -66,13 +66,22 @@ bool RTCStatsReport::AddStats(std::unique_ptr stats) { std::move(stats))).second; } -const RTCStats* RTCStatsReport::operator[](const std::string& id) const { +const RTCStats* RTCStatsReport::Get(const std::string& id) const { StatsMap::const_iterator it = stats_.find(id); if (it != stats_.cend()) return it->second.get(); return nullptr; } +void RTCStatsReport::TakeMembersFrom( + rtc::scoped_refptr victim) { + for (StatsMap::iterator it = victim->stats_.begin(); + it != victim->stats_.end(); ++it) { + AddStats(std::unique_ptr(it->second.release())); + } + victim->stats_.clear(); +} + RTCStatsReport::ConstIterator RTCStatsReport::begin() const { return ConstIterator(rtc::scoped_refptr(this), stats_.cbegin()); diff --git a/webrtc/stats/rtcstatsreport_unittest.cc b/webrtc/stats/rtcstatsreport_unittest.cc new file mode 100644 index 0000000000..b4722ab156 --- /dev/null +++ b/webrtc/stats/rtcstatsreport_unittest.cc @@ -0,0 +1,131 @@ +/* + * Copyright 2016 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 "webrtc/api/rtcstatsreport.h" + +#include "webrtc/api/rtcstats.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/gunit.h" + +namespace webrtc { + +class RTCTestStats1 : public RTCStats { + public: + RTCTestStats1(const std::string& id, double timestamp) + : RTCStats(id, timestamp), + integer("integer") {} + + WEBRTC_RTCSTATS_IMPL(RTCStats, RTCTestStats1, + &integer); + + RTCStatsMember integer; +}; + +const char RTCTestStats1::kType[] = "test-stats-1"; + +class RTCTestStats2 : public RTCStats { + public: + RTCTestStats2(const std::string& id, double timestamp) + : RTCStats(id, timestamp), + number("number") {} + + WEBRTC_RTCSTATS_IMPL(RTCStats, RTCTestStats2, + &number); + + RTCStatsMember number; +}; + +const char RTCTestStats2::kType[] = "test-stats-2"; + +class RTCTestStats3 : public RTCStats { + public: + RTCTestStats3(const std::string& id, double timestamp) + : RTCStats(id, timestamp), + string("string") {} + + WEBRTC_RTCSTATS_IMPL(RTCStats, RTCTestStats3, + &string); + + RTCStatsMember string; +}; + +const char RTCTestStats3::kType[] = "test-stats-3"; + +TEST(RTCStatsReport, AddAndGetStats) { + rtc::scoped_refptr report = RTCStatsReport::Create(); + EXPECT_EQ(report->size(), static_cast(0)); + report->AddStats(std::unique_ptr(new RTCTestStats1("a0", 1.0))); + report->AddStats(std::unique_ptr(new RTCTestStats1("a1", 2.0))); + report->AddStats(std::unique_ptr(new RTCTestStats2("b0", 4.0))); + report->AddStats(std::unique_ptr(new RTCTestStats2("b1", 8.0))); + report->AddStats(std::unique_ptr(new RTCTestStats1("a2", 16.0))); + report->AddStats(std::unique_ptr(new RTCTestStats2("b2", 32.0))); + EXPECT_EQ(report->size(), static_cast(6)); + + EXPECT_EQ(report->Get("missing"), nullptr); + EXPECT_EQ(report->Get("a0")->id(), "a0"); + EXPECT_EQ(report->Get("b2")->id(), "b2"); + + std::vector a = report->GetStatsOfType(); + EXPECT_EQ(a.size(), static_cast(3)); + uint32_t mask = 0; + for (const RTCTestStats1* stats : a) + mask |= static_cast(stats->timestamp()); + EXPECT_EQ(mask, static_cast(1 | 2 | 16)); + + std::vector b = report->GetStatsOfType(); + EXPECT_EQ(b.size(), static_cast(3)); + mask = 0; + for (const RTCTestStats2* stats : b) + mask |= static_cast(stats->timestamp()); + EXPECT_EQ(mask, static_cast(4 | 8 | 32)); + + EXPECT_EQ(report->GetStatsOfType().size(), + static_cast(0)); +} + +TEST(RTCStatsReport, StatsOrder) { + rtc::scoped_refptr report = RTCStatsReport::Create(); + report->AddStats(std::unique_ptr(new RTCTestStats1("C", 2.0))); + report->AddStats(std::unique_ptr(new RTCTestStats1("D", 3.0))); + report->AddStats(std::unique_ptr(new RTCTestStats2("B", 1.0))); + report->AddStats(std::unique_ptr(new RTCTestStats2("A", 0.0))); + report->AddStats(std::unique_ptr(new RTCTestStats2("E", 4.0))); + report->AddStats(std::unique_ptr(new RTCTestStats2("F", 5.0))); + report->AddStats(std::unique_ptr(new RTCTestStats2("G", 6.0))); + size_t i = 0; + for (const RTCStats& stats : *report) { + EXPECT_EQ(static_cast(stats.timestamp()), i); + ++i; + } + EXPECT_EQ(i, static_cast(7)); +} + +TEST(RTCStatsReport, TakeMembersFrom) { + rtc::scoped_refptr a = RTCStatsReport::Create(); + a->AddStats(std::unique_ptr(new RTCTestStats1("B", 1.0))); + a->AddStats(std::unique_ptr(new RTCTestStats1("C", 2.0))); + a->AddStats(std::unique_ptr(new RTCTestStats1("E", 4.0))); + rtc::scoped_refptr b = RTCStatsReport::Create(); + b->AddStats(std::unique_ptr(new RTCTestStats1("A", 0.0))); + b->AddStats(std::unique_ptr(new RTCTestStats1("D", 3.0))); + b->AddStats(std::unique_ptr(new RTCTestStats1("F", 5.0))); + + a->TakeMembersFrom(b); + EXPECT_EQ(b->size(), static_cast(0)); + size_t i = 0; + for (const RTCStats& stats : *a) { + EXPECT_EQ(static_cast(stats.timestamp()), i); + ++i; + } + EXPECT_EQ(i, static_cast(6)); +} + +} // namespace webrtc diff --git a/webrtc/stats/stats.gyp b/webrtc/stats/stats.gyp index 9310aabe99..4c2255711c 100644 --- a/webrtc/stats/stats.gyp +++ b/webrtc/stats/stats.gyp @@ -37,6 +37,7 @@ ], 'sources': [ 'rtcstats_unittest.cc', + 'rtcstatsreport_unittest.cc', ], }, ],