Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Side by Side Diff: webrtc/stats/rtcstatscollector_unittest.cc

Issue 2270033004: RTCStatsCollector collecting stats on multiple threads. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: (nits, no need to rerun bots yet) Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/stats/rtcstatscollector.h" 11 #include "webrtc/stats/rtcstatscollector.h"
12 12
13 #include <memory> 13 #include <memory>
14 #include <string> 14 #include <string>
15 #include <vector> 15 #include <vector>
16 16
17 #include "webrtc/api/jsepsessiondescription.h" 17 #include "webrtc/api/jsepsessiondescription.h"
18 #include "webrtc/api/rtcstats_objects.h" 18 #include "webrtc/api/rtcstats_objects.h"
19 #include "webrtc/api/rtcstatsreport.h" 19 #include "webrtc/api/rtcstatsreport.h"
20 #include "webrtc/api/test/mock_datachannel.h" 20 #include "webrtc/api/test/mock_datachannel.h"
21 #include "webrtc/api/test/mock_peerconnection.h" 21 #include "webrtc/api/test/mock_peerconnection.h"
22 #include "webrtc/api/test/mock_webrtcsession.h" 22 #include "webrtc/api/test/mock_webrtcsession.h"
23 #include "webrtc/base/checks.h" 23 #include "webrtc/base/checks.h"
24 #include "webrtc/base/gunit.h" 24 #include "webrtc/base/gunit.h"
25 #include "webrtc/base/logging.h" 25 #include "webrtc/base/logging.h"
26 #include "webrtc/base/test/faketiming.h" 26 #include "webrtc/base/test/faketiming.h"
27 #include "webrtc/base/thread_checker.h"
27 #include "webrtc/media/base/fakemediaengine.h" 28 #include "webrtc/media/base/fakemediaengine.h"
28 29
29 using testing::Return; 30 using testing::Return;
30 using testing::ReturnRef; 31 using testing::ReturnRef;
31 32
32 namespace webrtc { 33 namespace webrtc {
33 34
35 namespace {
36
37 const int64_t kGetStatsTimeoutMs = 1000;
38
34 class RTCStatsCollectorTester : public SetSessionDescriptionObserver { 39 class RTCStatsCollectorTester : public SetSessionDescriptionObserver {
35 public: 40 public:
36 RTCStatsCollectorTester() 41 RTCStatsCollectorTester()
37 : worker_thread_(rtc::Thread::Current()), 42 : worker_thread_(rtc::Thread::Current()),
38 network_thread_(rtc::Thread::Current()), 43 network_thread_(rtc::Thread::Current()),
39 channel_manager_(new cricket::ChannelManager( 44 channel_manager_(new cricket::ChannelManager(
40 new cricket::FakeMediaEngine(), 45 new cricket::FakeMediaEngine(),
41 worker_thread_, 46 worker_thread_,
42 network_thread_)), 47 network_thread_)),
43 media_controller_( 48 media_controller_(
(...skipping 23 matching lines...) Expand all
67 rtc::Thread* const worker_thread_; 72 rtc::Thread* const worker_thread_;
68 rtc::Thread* const network_thread_; 73 rtc::Thread* const network_thread_;
69 std::unique_ptr<cricket::ChannelManager> channel_manager_; 74 std::unique_ptr<cricket::ChannelManager> channel_manager_;
70 std::unique_ptr<webrtc::MediaControllerInterface> media_controller_; 75 std::unique_ptr<webrtc::MediaControllerInterface> media_controller_;
71 MockWebRtcSession session_; 76 MockWebRtcSession session_;
72 MockPeerConnection pc_; 77 MockPeerConnection pc_;
73 78
74 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_; 79 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_;
75 }; 80 };
76 81
82 class RTCTestStats : public RTCStats {
83 public:
84 RTCTestStats(const std::string& id, double timestamp)
85 : RTCStats(id, timestamp),
86 dummy_stat("dummyStat") {}
87
88 WEBRTC_RTCSTATS_IMPL(RTCStats, RTCTestStats,
89 &dummy_stat);
90
91 RTCStatsMember<int32_t> dummy_stat;
92 };
93
94 const char RTCTestStats::kType[] = "test-stats";
95
96 // Overrides the stats collection to verify thread usage and that the resulting
97 // partial reports are merged.
98 class FakeRTCStatsCollector : public RTCStatsCollector,
99 public RTCStatsCollectorCallback {
hta-webrtc 2016/08/31 09:57:36 If you're faking the implementation under test, th
hbos 2016/09/01 14:16:16 I wanted to test the threaded aspects of the class
100 public:
101 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
102 PeerConnection* pc,
103 double cache_lifetime,
104 std::unique_ptr<rtc::Timing> timing) {
105 return rtc::scoped_refptr<FakeRTCStatsCollector>(
106 new rtc::RefCountedObject<FakeRTCStatsCollector>(
107 pc, cache_lifetime, timing.release()));
108 }
109
110 void OnStatsDelivered(
111 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
112 EXPECT_TRUE(signaling_thread_->IsCurrent());
113 rtc::CritScope cs(&lock_);
114 delivered_report_ = report;
115 }
116
117 bool IsStatsDelivered() {
118 EXPECT_TRUE(signaling_thread_->IsCurrent());
119 rtc::CritScope cs(&lock_);
120 if (!delivered_report_)
121 return false;
122 EXPECT_EQ(produced_on_signaling_thread_, 1);
123 EXPECT_EQ(produced_on_worker_thread_, 1);
124 EXPECT_EQ(produced_on_network_thread_, 1);
125
126 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
127 EXPECT_TRUE(delivered_report_->Get("WorkerThreadStats"));
128 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
129
130 produced_on_signaling_thread_ = 0;
131 produced_on_worker_thread_ = 0;
132 produced_on_network_thread_ = 0;
133 delivered_report_ = nullptr;
134 return true;
135 }
136
137 protected:
138 FakeRTCStatsCollector(
139 PeerConnection* pc,
140 double cache_lifetime,
141 rtc::Timing* timing)
142 : RTCStatsCollector(pc, cache_lifetime, timing),
143 signaling_thread_(pc->session()->signaling_thread()),
144 worker_thread_(pc->session()->worker_thread()),
145 network_thread_(pc->session()->network_thread()) {
146 }
147
148 void ProducePartialResultsOnSignalingThread_s(double timestamp) override {
149 EXPECT_TRUE(signaling_thread_->IsCurrent());
150 {
151 rtc::CritScope cs(&lock_);
152 EXPECT_FALSE(delivered_report_);
153 ++produced_on_signaling_thread_;
154 }
155
156 rtc::scoped_refptr<RTCStatsReport> signaling_report =
157 RTCStatsReport::Create();
158 signaling_report->AddStats(std::unique_ptr<const RTCStats>(
159 new RTCTestStats("SignalingThreadStats", timestamp)));
160 AddPartialResults(signaling_report, timestamp);
161 }
162 void ProducePartialResultsOnWorkerThread_w(double timestamp) override {
163 EXPECT_TRUE(worker_thread_->IsCurrent());
164 {
165 rtc::CritScope cs(&lock_);
166 EXPECT_FALSE(delivered_report_);
167 ++produced_on_worker_thread_;
168 }
169
170 rtc::scoped_refptr<RTCStatsReport> worker_report = RTCStatsReport::Create();
171 worker_report->AddStats(std::unique_ptr<const RTCStats>(
172 new RTCTestStats("WorkerThreadStats", timestamp)));
173 AddPartialResults(worker_report, timestamp);
174 }
175 void ProducePartialResultsOnNetworkThread_n(double timestamp) override {
176 EXPECT_TRUE(network_thread_->IsCurrent());
177 {
178 rtc::CritScope cs(&lock_);
179 EXPECT_FALSE(delivered_report_);
180 ++produced_on_network_thread_;
181 }
182
183 rtc::scoped_refptr<RTCStatsReport> network_report =
184 RTCStatsReport::Create();
185 network_report->AddStats(std::unique_ptr<const RTCStats>(
186 new RTCTestStats("NetworkThreadStats", timestamp)));
187 AddPartialResults(network_report, timestamp);
188 }
189
190 private:
191 rtc::Thread* const signaling_thread_;
192 rtc::Thread* const worker_thread_;
193 rtc::Thread* const network_thread_;
194
195 rtc::CriticalSection lock_;
196 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
197 int produced_on_signaling_thread_ = 0;
198 int produced_on_worker_thread_ = 0;
199 int produced_on_network_thread_ = 0;
200 };
201
202 class StatsCallback : public RTCStatsCollectorCallback {
203 public:
204 static rtc::scoped_refptr<StatsCallback> Create(
205 rtc::scoped_refptr<const RTCStatsReport>* report_ptr = nullptr) {
206 return rtc::scoped_refptr<StatsCallback>(
207 new rtc::RefCountedObject<StatsCallback>(report_ptr));
208 }
209
210 void OnStatsDelivered(
211 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
212 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
213 report_ = report;
214 if (report_ptr_)
215 *report_ptr_ = report_;
216 }
217
218 rtc::scoped_refptr<const RTCStatsReport> report() const {
219 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
220 return report_;
221 }
222
223 protected:
224 explicit StatsCallback(rtc::scoped_refptr<const RTCStatsReport>* report_ptr)
225 : report_ptr_(report_ptr) {}
226
227 private:
228 rtc::ThreadChecker thread_checker_;
229 rtc::scoped_refptr<const RTCStatsReport> report_;
230 rtc::scoped_refptr<const RTCStatsReport>* report_ptr_;
231 };
232
233 } // namespace
234
77 class RTCStatsCollectorTest : public testing::Test { 235 class RTCStatsCollectorTest : public testing::Test {
78 public: 236 public:
237 static const bool kUseRealCollector = false;
238 static const bool kUseFakeCollector = true;
239
79 RTCStatsCollectorTest() 240 RTCStatsCollectorTest()
80 : test_(new rtc::RefCountedObject<RTCStatsCollectorTester>()), 241 : test_(new rtc::RefCountedObject<RTCStatsCollectorTester>()),
81 timing_(new rtc::FakeTiming()), 242 timing_(new rtc::FakeTiming()) {
82 collector_(&test_->pc(), 0.05, std::unique_ptr<rtc::Timing>(timing_)) { 243 }
244
245 void InitCollector(bool fake_collector) {
hta-webrtc 2016/08/31 09:57:36 Not a good code smell. If you really need to have
hbos 2016/09/01 14:16:16 Done.
246 EXPECT_FALSE(collector_);
247 fake_collector_ = fake_collector;
248 if (!fake_collector_) {
249 collector_ = RTCStatsCollector::Create(
250 &test_->pc(), 0.05, std::unique_ptr<rtc::Timing>(timing_));
251 } else {
252 rtc::scoped_refptr<FakeRTCStatsCollector> fake_collector =
253 FakeRTCStatsCollector::Create(
254 &test_->pc(), 0.05, std::unique_ptr<rtc::Timing>(timing_));
255 collector_ = fake_collector;
256 }
257 }
258
259 FakeRTCStatsCollector* fake_collector() const {
260 EXPECT_TRUE(fake_collector_);
261 return static_cast<FakeRTCStatsCollector*>(collector_.get());
262 }
263
264 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
265 EXPECT_TRUE(collector_);
266 rtc::scoped_refptr<StatsCallback> callback = StatsCallback::Create();
267 collector_->GetStatsReport(callback);
268 EXPECT_TRUE_WAIT(callback->report(), kGetStatsTimeoutMs);
269 return callback->report();
83 } 270 }
84 271
85 protected: 272 protected:
86 rtc::scoped_refptr<RTCStatsCollectorTester> test_; 273 rtc::scoped_refptr<RTCStatsCollectorTester> test_;
87 rtc::FakeTiming* timing_; // Owned by |collector_|. 274 rtc::FakeTiming* timing_; // Owned by |collector_|.
88 RTCStatsCollector collector_; 275 rtc::scoped_refptr<RTCStatsCollector> collector_;
89 }; 276 bool fake_collector_ = false;
277 };
278
279 // With a fake collector verify that stats are collected on all threads and that
280 // the partial results are assembled into a final report with all results.
281 TEST_F(RTCStatsCollectorTest, VerifyThreadUsageAndMergedResults) {
282 InitCollector(kUseFakeCollector);
283 collector_->GetStatsReport(fake_collector());
284 // |IsStatsDelivered| also verifies the results.
285 EXPECT_TRUE_WAIT(fake_collector()->IsStatsDelivered(), kGetStatsTimeoutMs);
286 }
287
288 // Verify that the callback is kept alive and still invoked even if the only
289 // reference to it is by |GetStatsReport|.
290 TEST_F(RTCStatsCollectorTest, CallbackNoExternalReferences) {
291 InitCollector(kUseFakeCollector);
292 rtc::scoped_refptr<const RTCStatsReport> result;
293 collector_->GetStatsReport(StatsCallback::Create(&result));
294 EXPECT_TRUE_WAIT(result, kGetStatsTimeoutMs);
295 }
hta-webrtc 2016/08/31 09:57:36 Please add a test that calls GetStatsReport() twic
hbos 2016/09/01 14:16:16 Done. The FakeClock unfortunately processes messag
90 296
91 TEST_F(RTCStatsCollectorTest, CachedStatsReport) { 297 TEST_F(RTCStatsCollectorTest, CachedStatsReport) {
298 InitCollector(kUseRealCollector);
92 // Caching should ensure |a| and |b| are the same report. 299 // Caching should ensure |a| and |b| are the same report.
93 rtc::scoped_refptr<const RTCStatsReport> a = collector_.GetStatsReport(); 300 rtc::scoped_refptr<const RTCStatsReport> a = GetStatsReport();
94 rtc::scoped_refptr<const RTCStatsReport> b = collector_.GetStatsReport(); 301 rtc::scoped_refptr<const RTCStatsReport> b = GetStatsReport();
95 EXPECT_TRUE(a);
96 EXPECT_EQ(a.get(), b.get()); 302 EXPECT_EQ(a.get(), b.get());
97 // Invalidate cache by clearing it. 303 // Invalidate cache by clearing it.
98 collector_.ClearCachedStatsReport(); 304 collector_->ClearCachedStatsReport();
99 rtc::scoped_refptr<const RTCStatsReport> c = collector_.GetStatsReport(); 305 rtc::scoped_refptr<const RTCStatsReport> c = GetStatsReport();
100 EXPECT_TRUE(c);
101 EXPECT_NE(b.get(), c.get()); 306 EXPECT_NE(b.get(), c.get());
102 // Invalidate cache by advancing time. 307 // Invalidate cache by advancing time.
103 timing_->AdvanceTimeMillisecs(51.0); 308 timing_->AdvanceTimeMillisecs(51.0);
104 rtc::scoped_refptr<const RTCStatsReport> d = collector_.GetStatsReport(); 309 rtc::scoped_refptr<const RTCStatsReport> d = GetStatsReport();
105 EXPECT_TRUE(d);
106 EXPECT_NE(c.get(), d.get()); 310 EXPECT_NE(c.get(), d.get());
107 } 311 }
108 312
109 TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) { 313 TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
110 rtc::scoped_refptr<const RTCStatsReport> report = collector_.GetStatsReport(); 314 InitCollector(kUseRealCollector);
315 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
111 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(), 316 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
112 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats."; 317 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
113 const RTCStats* stats = report->Get("RTCPeerConnection"); 318 const RTCStats* stats = report->Get("RTCPeerConnection");
114 EXPECT_TRUE(stats); 319 EXPECT_TRUE(stats);
115 EXPECT_EQ(stats->timestamp(), timing_->TimerNow()); 320 EXPECT_EQ(stats->timestamp(), timing_->TimerNow());
116 { 321 {
117 // Expected stats with no data channels 322 // Expected stats with no data channels
118 const RTCPeerConnectionStats& pcstats = 323 const RTCPeerConnectionStats& pcstats =
119 stats->cast_to<RTCPeerConnectionStats>(); 324 stats->cast_to<RTCPeerConnectionStats>();
120 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(0)); 325 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(0));
121 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(0)); 326 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(0));
122 } 327 }
123 328
124 test_->data_channels().push_back( 329 test_->data_channels().push_back(
125 new MockDataChannel(DataChannelInterface::kConnecting)); 330 new MockDataChannel(DataChannelInterface::kConnecting));
126 test_->data_channels().push_back( 331 test_->data_channels().push_back(
127 new MockDataChannel(DataChannelInterface::kOpen)); 332 new MockDataChannel(DataChannelInterface::kOpen));
128 test_->data_channels().push_back( 333 test_->data_channels().push_back(
129 new MockDataChannel(DataChannelInterface::kClosing)); 334 new MockDataChannel(DataChannelInterface::kClosing));
130 test_->data_channels().push_back( 335 test_->data_channels().push_back(
131 new MockDataChannel(DataChannelInterface::kClosed)); 336 new MockDataChannel(DataChannelInterface::kClosed));
132 337
133 collector_.ClearCachedStatsReport(); 338 collector_->ClearCachedStatsReport();
134 report = collector_.GetStatsReport(); 339 report = GetStatsReport();
135 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(), 340 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
136 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats."; 341 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
137 stats = report->Get("RTCPeerConnection"); 342 stats = report->Get("RTCPeerConnection");
138 EXPECT_TRUE(stats); 343 EXPECT_TRUE(stats);
139 { 344 {
140 // Expected stats with the above four data channels 345 // Expected stats with the above four data channels
141 // TODO(hbos): When the |RTCPeerConnectionStats| is the number of data 346 // TODO(hbos): When the |RTCPeerConnectionStats| is the number of data
142 // channels that have been opened and closed, not the numbers currently 347 // channels that have been opened and closed, not the numbers currently
143 // open/closed, we would expect opened >= closed and (opened - closed) to be 348 // open/closed, we would expect opened >= closed and (opened - closed) to be
144 // the number currently open. crbug.com/636818. 349 // the number currently open. crbug.com/636818.
145 const RTCPeerConnectionStats& pcstats = 350 const RTCPeerConnectionStats& pcstats =
146 stats->cast_to<RTCPeerConnectionStats>(); 351 stats->cast_to<RTCPeerConnectionStats>();
147 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(1)); 352 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(1));
148 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(3)); 353 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(3));
149 } 354 }
150 } 355 }
151 356
152 } // namespace webrtc 357 } // namespace webrtc
OLDNEW
« webrtc/stats/rtcstatscollector.cc ('K') | « webrtc/stats/rtcstatscollector.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698