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