This is part of the work to add a selector argument to getStats(). Changes: - TakeReferencedStats() added, which traverses the stats graph and takes any stats from the report that are directly or indirectly accessible from the starting stats objects in the stats graph. The result is returned as a stats report. - GetStatsReferencedIds(), an efficient helper function for getting neighbor stats object IDs. - RTCStatsReport::Take(), removed the stats object with the given ID and returns ownership of it (so that it can be added to another report). TakeReferencedStats() is tested with a bunch of sample stats graphs. GetStatsReferencedIds() is tested in the rtcstats_integrationttest.cc, making sure the expected IDs are returned. The expected IDs are the values of the stats object members with the "Id" or "Ids" suffix. Design doc: https://docs.google.com/document/d/18BywbtXgHCjsbR5nWBedpzqDjAfXrFSTJNiADnzoK0w/edit?usp=sharing Bug: chromium:680172 Change-Id: I5da9da8250da0cb05adb864015901393a4290776 Reviewed-on: https://webrtc-review.googlesource.com/60869 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22381}
149 lines
5.1 KiB
C++
149 lines
5.1 KiB
C++
/*
|
|
* 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 "api/stats/rtcstatsreport.h"
|
|
|
|
#include "api/stats/rtcstats.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/gunit.h"
|
|
|
|
namespace webrtc {
|
|
|
|
class RTCTestStats1 : public RTCStats {
|
|
public:
|
|
WEBRTC_RTCSTATS_DECL();
|
|
|
|
RTCTestStats1(const std::string& id, int64_t timestamp_us)
|
|
: RTCStats(id, timestamp_us),
|
|
integer("integer") {}
|
|
|
|
RTCStatsMember<int32_t> integer;
|
|
};
|
|
|
|
WEBRTC_RTCSTATS_IMPL(RTCTestStats1, RTCStats, "test-stats-1",
|
|
&integer);
|
|
|
|
class RTCTestStats2 : public RTCStats {
|
|
public:
|
|
WEBRTC_RTCSTATS_DECL();
|
|
|
|
RTCTestStats2(const std::string& id, int64_t timestamp_us)
|
|
: RTCStats(id, timestamp_us),
|
|
number("number") {}
|
|
|
|
RTCStatsMember<double> number;
|
|
};
|
|
|
|
WEBRTC_RTCSTATS_IMPL(RTCTestStats2, RTCStats, "test-stats-2",
|
|
&number);
|
|
|
|
class RTCTestStats3 : public RTCStats {
|
|
public:
|
|
WEBRTC_RTCSTATS_DECL();
|
|
|
|
RTCTestStats3(const std::string& id, int64_t timestamp_us)
|
|
: RTCStats(id, timestamp_us),
|
|
string("string") {}
|
|
|
|
RTCStatsMember<std::string> string;
|
|
};
|
|
|
|
WEBRTC_RTCSTATS_IMPL(RTCTestStats3, RTCStats, "test-stats-3",
|
|
&string);
|
|
|
|
TEST(RTCStatsReport, AddAndGetStats) {
|
|
rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(1337);
|
|
EXPECT_EQ(report->timestamp_us(), 1337u);
|
|
EXPECT_EQ(report->size(), static_cast<size_t>(0));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("a0", 1)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("a1", 2)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats2("b0", 4)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats2("b1", 8)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("a2", 16)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats2("b2", 32)));
|
|
EXPECT_EQ(report->size(), static_cast<size_t>(6));
|
|
|
|
EXPECT_EQ(report->Get("missing"), nullptr);
|
|
EXPECT_EQ(report->Get("a0")->id(), "a0");
|
|
EXPECT_EQ(report->Get("b2")->id(), "b2");
|
|
|
|
std::vector<const RTCTestStats1*> a = report->GetStatsOfType<RTCTestStats1>();
|
|
EXPECT_EQ(a.size(), static_cast<size_t>(3));
|
|
int64_t mask = 0;
|
|
for (const RTCTestStats1* stats : a)
|
|
mask |= stats->timestamp_us();
|
|
EXPECT_EQ(mask, static_cast<int64_t>(1 | 2 | 16));
|
|
|
|
std::vector<const RTCTestStats2*> b = report->GetStatsOfType<RTCTestStats2>();
|
|
EXPECT_EQ(b.size(), static_cast<size_t>(3));
|
|
mask = 0;
|
|
for (const RTCTestStats2* stats : b)
|
|
mask |= stats->timestamp_us();
|
|
EXPECT_EQ(mask, static_cast<int64_t>(4 | 8 | 32));
|
|
|
|
EXPECT_EQ(report->GetStatsOfType<RTCTestStats3>().size(),
|
|
static_cast<size_t>(0));
|
|
}
|
|
|
|
TEST(RTCStatsReport, StatsOrder) {
|
|
rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(1337);
|
|
EXPECT_EQ(report->timestamp_us(), 1337u);
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("C", 2)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("D", 3)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats2("B", 1)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats2("A", 0)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats2("E", 4)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats2("F", 5)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats2("G", 6)));
|
|
int64_t i = 0;
|
|
for (const RTCStats& stats : *report) {
|
|
EXPECT_EQ(stats.timestamp_us(), i);
|
|
++i;
|
|
}
|
|
EXPECT_EQ(i, static_cast<int64_t>(7));
|
|
}
|
|
|
|
TEST(RTCStatsReport, Take) {
|
|
rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(0);
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("A", 1)));
|
|
report->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("B", 2)));
|
|
EXPECT_TRUE(report->Get("A"));
|
|
EXPECT_EQ(report->size(), 2u);
|
|
auto a = report->Take("A");
|
|
EXPECT_TRUE(a);
|
|
EXPECT_EQ(report->size(), 1u);
|
|
EXPECT_FALSE(report->Get("A"));
|
|
EXPECT_FALSE(report->Take("A"));
|
|
}
|
|
|
|
TEST(RTCStatsReport, TakeMembersFrom) {
|
|
rtc::scoped_refptr<RTCStatsReport> a = RTCStatsReport::Create(1337);
|
|
EXPECT_EQ(a->timestamp_us(), 1337u);
|
|
a->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("B", 1)));
|
|
a->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("C", 2)));
|
|
a->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("E", 4)));
|
|
rtc::scoped_refptr<RTCStatsReport> b = RTCStatsReport::Create(1338);
|
|
EXPECT_EQ(b->timestamp_us(), 1338u);
|
|
b->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("A", 0)));
|
|
b->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("D", 3)));
|
|
b->AddStats(std::unique_ptr<RTCStats>(new RTCTestStats1("F", 5)));
|
|
|
|
a->TakeMembersFrom(b);
|
|
EXPECT_EQ(b->size(), static_cast<size_t>(0));
|
|
int64_t i = 0;
|
|
for (const RTCStats& stats : *a) {
|
|
EXPECT_EQ(stats.timestamp_us(), i);
|
|
++i;
|
|
}
|
|
EXPECT_EQ(i, static_cast<int64_t>(6));
|
|
}
|
|
|
|
} // namespace webrtc
|