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