1 /*
2 * Copyright 2018 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "pc/rtc_stats_traversal.h"
12
13 #include <memory>
14 #include <vector>
15
16 #include "api/stats/rtcstats_objects.h"
17 #include "test/gtest.h"
18
19 // This file contains tests for TakeReferencedStats().
20 // GetStatsNeighborIds() is tested in rtcstats_integrationtest.cc.
21
22 namespace webrtc {
23
24 class RTCStatsTraversalTest : public ::testing::Test {
25 public:
RTCStatsTraversalTest()26 RTCStatsTraversalTest() {
27 transport_ = new RTCTransportStats("transport", 0);
28 candidate_pair_ = new RTCIceCandidatePairStats("candidate-pair", 0);
29 local_candidate_ = new RTCLocalIceCandidateStats("local-candidate", 0);
30 remote_candidate_ = new RTCRemoteIceCandidateStats("remote-candidate", 0);
31 initial_report_ = RTCStatsReport::Create(Timestamp::Zero());
32 initial_report_->AddStats(std::unique_ptr<const RTCStats>(transport_));
33 initial_report_->AddStats(std::unique_ptr<const RTCStats>(candidate_pair_));
34 initial_report_->AddStats(
35 std::unique_ptr<const RTCStats>(local_candidate_));
36 initial_report_->AddStats(
37 std::unique_ptr<const RTCStats>(remote_candidate_));
38 result_ = RTCStatsReport::Create(Timestamp::Zero());
39 }
40
TakeReferencedStats(std::vector<const RTCStats * > start_nodes)41 void TakeReferencedStats(std::vector<const RTCStats*> start_nodes) {
42 std::vector<std::string> start_ids;
43 start_ids.reserve(start_nodes.size());
44 for (const RTCStats* start_node : start_nodes) {
45 start_ids.push_back(start_node->id());
46 }
47 result_ = webrtc::TakeReferencedStats(initial_report_, start_ids);
48 }
49
EXPECT_VISITED(const RTCStats * stats)50 void EXPECT_VISITED(const RTCStats* stats) {
51 EXPECT_FALSE(initial_report_->Get(stats->id()))
52 << '"' << stats->id()
53 << "\" should be visited but it was not removed from initial report.";
54 EXPECT_TRUE(result_->Get(stats->id()))
55 << '"' << stats->id()
56 << "\" should be visited but it was not added to the resulting report.";
57 }
58
EXPECT_UNVISITED(const RTCStats * stats)59 void EXPECT_UNVISITED(const RTCStats* stats) {
60 EXPECT_TRUE(initial_report_->Get(stats->id()))
61 << '"' << stats->id()
62 << "\" should not be visited but it was removed from initial report.";
63 EXPECT_FALSE(result_->Get(stats->id()))
64 << '"' << stats->id()
65 << "\" should not be visited but it was added to the resulting report.";
66 }
67
68 protected:
69 rtc::scoped_refptr<RTCStatsReport> initial_report_;
70 rtc::scoped_refptr<RTCStatsReport> result_;
71 // Raw pointers to stats owned by the reports.
72 RTCTransportStats* transport_;
73 RTCIceCandidatePairStats* candidate_pair_;
74 RTCIceCandidateStats* local_candidate_;
75 RTCIceCandidateStats* remote_candidate_;
76 };
77
TEST_F(RTCStatsTraversalTest,NoReachableConnections)78 TEST_F(RTCStatsTraversalTest, NoReachableConnections) {
79 // Everything references transport but transport doesn't reference anything.
80 //
81 // candidate-pair
82 // | | |
83 // v | v
84 // local-candidate | remote-candidate
85 // | | |
86 // v v v
87 // start:transport
88 candidate_pair_->transport_id = "transport";
89 candidate_pair_->local_candidate_id = "local-candidate";
90 candidate_pair_->remote_candidate_id = "remote-candidate";
91 local_candidate_->transport_id = "transport";
92 remote_candidate_->transport_id = "transport";
93 TakeReferencedStats({transport_});
94 EXPECT_VISITED(transport_);
95 EXPECT_UNVISITED(candidate_pair_);
96 EXPECT_UNVISITED(local_candidate_);
97 EXPECT_UNVISITED(remote_candidate_);
98 }
99
TEST_F(RTCStatsTraversalTest,SelfReference)100 TEST_F(RTCStatsTraversalTest, SelfReference) {
101 transport_->rtcp_transport_stats_id = "transport";
102 TakeReferencedStats({transport_});
103 EXPECT_VISITED(transport_);
104 EXPECT_UNVISITED(candidate_pair_);
105 EXPECT_UNVISITED(local_candidate_);
106 EXPECT_UNVISITED(remote_candidate_);
107 }
108
TEST_F(RTCStatsTraversalTest,BogusReference)109 TEST_F(RTCStatsTraversalTest, BogusReference) {
110 transport_->rtcp_transport_stats_id = "bogus-reference";
111 TakeReferencedStats({transport_});
112 EXPECT_VISITED(transport_);
113 EXPECT_UNVISITED(candidate_pair_);
114 EXPECT_UNVISITED(local_candidate_);
115 EXPECT_UNVISITED(remote_candidate_);
116 }
117
TEST_F(RTCStatsTraversalTest,Tree)118 TEST_F(RTCStatsTraversalTest, Tree) {
119 // start:candidate-pair
120 // | |
121 // v v
122 // local-candidate remote-candidate
123 // |
124 // v
125 // transport
126 candidate_pair_->local_candidate_id = "local-candidate";
127 candidate_pair_->remote_candidate_id = "remote-candidate";
128 local_candidate_->transport_id = "transport";
129 TakeReferencedStats({candidate_pair_});
130 EXPECT_VISITED(transport_);
131 EXPECT_VISITED(candidate_pair_);
132 EXPECT_VISITED(local_candidate_);
133 EXPECT_VISITED(remote_candidate_);
134 }
135
TEST_F(RTCStatsTraversalTest,MultiplePathsToSameNode)136 TEST_F(RTCStatsTraversalTest, MultiplePathsToSameNode) {
137 // start:candidate-pair
138 // | |
139 // v v
140 // local-candidate remote-candidate
141 // | |
142 // v v
143 // transport
144 candidate_pair_->local_candidate_id = "local-candidate";
145 candidate_pair_->remote_candidate_id = "remote-candidate";
146 local_candidate_->transport_id = "transport";
147 remote_candidate_->transport_id = "transport";
148 TakeReferencedStats({candidate_pair_});
149 EXPECT_VISITED(transport_);
150 EXPECT_VISITED(candidate_pair_);
151 EXPECT_VISITED(local_candidate_);
152 EXPECT_VISITED(remote_candidate_);
153 }
154
TEST_F(RTCStatsTraversalTest,CyclicGraph)155 TEST_F(RTCStatsTraversalTest, CyclicGraph) {
156 // candidate-pair
157 // | ^
158 // v |
159 // start:local-candidate | remote-candidate
160 // | |
161 // v |
162 // transport
163 local_candidate_->transport_id = "transport";
164 transport_->selected_candidate_pair_id = "candidate-pair";
165 candidate_pair_->local_candidate_id = "local-candidate";
166 TakeReferencedStats({local_candidate_});
167 EXPECT_VISITED(transport_);
168 EXPECT_VISITED(candidate_pair_);
169 EXPECT_VISITED(local_candidate_);
170 EXPECT_UNVISITED(remote_candidate_);
171 }
172
TEST_F(RTCStatsTraversalTest,MultipleStarts)173 TEST_F(RTCStatsTraversalTest, MultipleStarts) {
174 // start:candidate-pair
175 // |
176 // v
177 // local-candidate remote-candidate
178 // |
179 // v
180 // start:transport
181 candidate_pair_->remote_candidate_id = "remote-candidate";
182 local_candidate_->transport_id = "transport";
183 TakeReferencedStats({candidate_pair_, transport_});
184 EXPECT_VISITED(transport_);
185 EXPECT_VISITED(candidate_pair_);
186 EXPECT_UNVISITED(local_candidate_);
187 EXPECT_VISITED(remote_candidate_);
188 }
189
TEST_F(RTCStatsTraversalTest,MultipleStartsLeadingToSameNode)190 TEST_F(RTCStatsTraversalTest, MultipleStartsLeadingToSameNode) {
191 // candidate-pair
192 //
193 //
194 // start:local-candidate start:remote-candidate
195 // | |
196 // v v
197 // transport
198 local_candidate_->transport_id = "transport";
199 remote_candidate_->transport_id = "transport";
200 TakeReferencedStats({local_candidate_, remote_candidate_});
201 EXPECT_VISITED(transport_);
202 EXPECT_UNVISITED(candidate_pair_);
203 EXPECT_VISITED(local_candidate_);
204 EXPECT_VISITED(remote_candidate_);
205 }
206
207 } // namespace webrtc
208