blob: 32f8c8e5e1c65263c4e9a98f25221ce8dd56be52 [file] [log] [blame]
asapersson0e9d6d92016-05-23 06:07:55 -07001/*
2 * Copyright (c) 2016 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "video/stats_counter.h"
asapersson0e9d6d92016-05-23 06:07:55 -070012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "system_wrappers/include/clock.h"
14#include "test/gtest.h"
asapersson0e9d6d92016-05-23 06:07:55 -070015
16namespace webrtc {
17namespace {
asaperssone402a142016-10-06 23:39:15 -070018const int kDefaultProcessIntervalMs = 2000;
asaperssonfe647f42016-11-01 00:21:34 -070019const uint32_t kStreamId = 123456;
asapersson0e9d6d92016-05-23 06:07:55 -070020
21class StatsCounterObserverImpl : public StatsCounterObserver {
22 public:
23 StatsCounterObserverImpl() : num_calls_(0), last_sample_(-1) {}
24 void OnMetricUpdated(int sample) override {
25 ++num_calls_;
26 last_sample_ = sample;
27 }
28 int num_calls_;
29 int last_sample_;
30};
31} // namespace
32
33class StatsCounterTest : public ::testing::Test {
34 protected:
Yves Gerey665174f2018-06-19 15:03:05 +020035 StatsCounterTest() : clock_(1234) {}
asapersson0e9d6d92016-05-23 06:07:55 -070036
37 void AddSampleAndAdvance(int sample, int interval_ms, AvgCounter* counter) {
38 counter->Add(sample);
39 clock_.AdvanceTimeMilliseconds(interval_ms);
40 }
41
42 void SetSampleAndAdvance(int sample,
43 int interval_ms,
44 RateAccCounter* counter) {
asaperssonfe647f42016-11-01 00:21:34 -070045 counter->Set(sample, kStreamId);
asapersson0e9d6d92016-05-23 06:07:55 -070046 clock_.AdvanceTimeMilliseconds(interval_ms);
47 }
48
49 void VerifyStatsIsNotSet(const AggregatedStats& stats) {
50 EXPECT_EQ(0, stats.num_samples);
51 EXPECT_EQ(-1, stats.min);
52 EXPECT_EQ(-1, stats.max);
53 EXPECT_EQ(-1, stats.average);
54 }
55
56 SimulatedClock clock_;
57};
58
59TEST_F(StatsCounterTest, NoSamples) {
asaperssonce2e1362016-09-09 00:13:35 -070060 AvgCounter counter(&clock_, nullptr, false);
asapersson0e9d6d92016-05-23 06:07:55 -070061 VerifyStatsIsNotSet(counter.GetStats());
62}
63
64TEST_F(StatsCounterTest, TestRegisterObserver) {
65 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
66 const int kSample = 22;
asaperssonce2e1362016-09-09 00:13:35 -070067 AvgCounter counter(&clock_, observer, false);
asaperssone402a142016-10-06 23:39:15 -070068 AddSampleAndAdvance(kSample, kDefaultProcessIntervalMs, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -070069 // Trigger process (sample included in next interval).
70 counter.Add(111);
71 EXPECT_EQ(1, observer->num_calls_);
72}
73
asapersson250fd972016-09-08 00:07:21 -070074TEST_F(StatsCounterTest, HasSample) {
asaperssonce2e1362016-09-09 00:13:35 -070075 AvgCounter counter(&clock_, nullptr, false);
asapersson250fd972016-09-08 00:07:21 -070076 EXPECT_FALSE(counter.HasSample());
77 counter.Add(1);
78 EXPECT_TRUE(counter.HasSample());
79}
80
asapersson0e9d6d92016-05-23 06:07:55 -070081TEST_F(StatsCounterTest, VerifyProcessInterval) {
82 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asaperssonce2e1362016-09-09 00:13:35 -070083 AvgCounter counter(&clock_, observer, false);
asapersson0e9d6d92016-05-23 06:07:55 -070084 counter.Add(4);
asaperssone402a142016-10-06 23:39:15 -070085 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
asapersson0e9d6d92016-05-23 06:07:55 -070086 // Try trigger process (interval has not passed).
87 counter.Add(8);
88 EXPECT_EQ(0, observer->num_calls_);
89 VerifyStatsIsNotSet(counter.GetStats());
90 // Make process interval pass.
91 clock_.AdvanceTimeMilliseconds(1);
92 // Trigger process (sample included in next interval).
93 counter.Add(111);
94 EXPECT_EQ(1, observer->num_calls_);
95 EXPECT_EQ(6, observer->last_sample_);
96 // Aggregated stats.
97 AggregatedStats stats = counter.GetStats();
98 EXPECT_EQ(1, stats.num_samples);
99}
100
101TEST_F(StatsCounterTest, TestMetric_AvgCounter) {
102 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asaperssonce2e1362016-09-09 00:13:35 -0700103 AvgCounter counter(&clock_, observer, false);
asapersson0e9d6d92016-05-23 06:07:55 -0700104 counter.Add(4);
105 counter.Add(8);
106 counter.Add(9);
asaperssone402a142016-10-06 23:39:15 -0700107 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700108 // Trigger process (sample included in next interval).
109 counter.Add(111);
110 // Average per interval.
111 EXPECT_EQ(1, observer->num_calls_);
112 EXPECT_EQ(7, observer->last_sample_);
113 // Aggregated stats.
114 AggregatedStats stats = counter.GetStats();
115 EXPECT_EQ(1, stats.num_samples);
116 EXPECT_EQ(7, stats.min);
117 EXPECT_EQ(7, stats.max);
118 EXPECT_EQ(7, stats.average);
119}
120
121TEST_F(StatsCounterTest, TestMetric_MaxCounter) {
asaperssone402a142016-10-06 23:39:15 -0700122 const int64_t kProcessIntervalMs = 1000;
asapersson0e9d6d92016-05-23 06:07:55 -0700123 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asaperssone402a142016-10-06 23:39:15 -0700124 MaxCounter counter(&clock_, observer, kProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700125 counter.Add(4);
126 counter.Add(9);
127 counter.Add(8);
128 clock_.AdvanceTimeMilliseconds(kProcessIntervalMs);
129 // Trigger process (sample included in next interval).
130 counter.Add(111);
131 // Average per interval.
132 EXPECT_EQ(1, observer->num_calls_);
133 EXPECT_EQ(9, observer->last_sample_);
134 // Aggregated stats.
135 AggregatedStats stats = counter.GetStats();
136 EXPECT_EQ(1, stats.num_samples);
137 EXPECT_EQ(9, stats.min);
138 EXPECT_EQ(9, stats.max);
139 EXPECT_EQ(9, stats.average);
140}
141
142TEST_F(StatsCounterTest, TestMetric_PercentCounter) {
143 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
144 PercentCounter counter(&clock_, observer);
145 counter.Add(true);
146 counter.Add(false);
asaperssone402a142016-10-06 23:39:15 -0700147 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700148 // Trigger process (sample included in next interval).
149 counter.Add(false);
150 // Percentage per interval.
151 EXPECT_EQ(1, observer->num_calls_);
152 EXPECT_EQ(50, observer->last_sample_);
153 // Aggregated stats.
154 AggregatedStats stats = counter.GetStats();
155 EXPECT_EQ(1, stats.num_samples);
156 EXPECT_EQ(50, stats.min);
157 EXPECT_EQ(50, stats.max);
158}
159
160TEST_F(StatsCounterTest, TestMetric_PermilleCounter) {
161 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
162 PermilleCounter counter(&clock_, observer);
163 counter.Add(true);
164 counter.Add(false);
asaperssone402a142016-10-06 23:39:15 -0700165 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700166 // Trigger process (sample included in next interval).
167 counter.Add(false);
168 // Permille per interval.
169 EXPECT_EQ(1, observer->num_calls_);
170 EXPECT_EQ(500, observer->last_sample_);
171 // Aggregated stats.
172 AggregatedStats stats = counter.GetStats();
173 EXPECT_EQ(1, stats.num_samples);
174 EXPECT_EQ(500, stats.min);
175 EXPECT_EQ(500, stats.max);
176}
177
178TEST_F(StatsCounterTest, TestMetric_RateCounter) {
179 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asapersson5093b382016-08-15 01:20:30 -0700180 RateCounter counter(&clock_, observer, true);
asapersson0e9d6d92016-05-23 06:07:55 -0700181 counter.Add(186);
182 counter.Add(350);
183 counter.Add(22);
asaperssone402a142016-10-06 23:39:15 -0700184 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700185 // Trigger process (sample included in next interval).
186 counter.Add(111);
187 // Rate per interval, (186 + 350 + 22) / 2 sec = 279 samples/sec
188 EXPECT_EQ(1, observer->num_calls_);
189 EXPECT_EQ(279, observer->last_sample_);
190 // Aggregated stats.
191 AggregatedStats stats = counter.GetStats();
192 EXPECT_EQ(1, stats.num_samples);
193 EXPECT_EQ(279, stats.min);
194 EXPECT_EQ(279, stats.max);
195}
196
197TEST_F(StatsCounterTest, TestMetric_RateAccCounter) {
198 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asapersson5093b382016-08-15 01:20:30 -0700199 RateAccCounter counter(&clock_, observer, true);
asaperssonfe647f42016-11-01 00:21:34 -0700200 counter.Set(175, kStreamId);
201 counter.Set(188, kStreamId);
asaperssone402a142016-10-06 23:39:15 -0700202 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700203 // Trigger process (sample included in next interval).
asaperssonfe647f42016-11-01 00:21:34 -0700204 counter.Set(192, kStreamId);
asapersson0e9d6d92016-05-23 06:07:55 -0700205 // Rate per interval: (188 - 0) / 2 sec = 94 samples/sec
206 EXPECT_EQ(1, observer->num_calls_);
207 EXPECT_EQ(94, observer->last_sample_);
208 // Aggregated stats.
209 AggregatedStats stats = counter.GetStats();
210 EXPECT_EQ(1, stats.num_samples);
211 EXPECT_EQ(94, stats.min);
212 EXPECT_EQ(94, stats.max);
213}
214
asapersson93e1e232017-02-06 05:18:35 -0800215TEST_F(StatsCounterTest, TestMetric_RateAccCounterWithSetLast) {
216 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
217 RateAccCounter counter(&clock_, observer, true);
218 counter.SetLast(98, kStreamId);
219 counter.Set(175, kStreamId);
220 counter.Set(188, kStreamId);
221 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
222 // Trigger process (sample included in next interval).
223 counter.Set(192, kStreamId);
224 // Rate per interval: (188 - 98) / 2 sec = 45 samples/sec
225 EXPECT_EQ(1, observer->num_calls_);
226 EXPECT_EQ(45, observer->last_sample_);
227}
228
asaperssonfe647f42016-11-01 00:21:34 -0700229TEST_F(StatsCounterTest, TestMetric_RateAccCounterWithMultipleStreamIds) {
230 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
231 RateAccCounter counter(&clock_, observer, true);
232 counter.Set(175, kStreamId);
233 counter.Set(188, kStreamId);
234 counter.Set(100, kStreamId + 1);
235 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
236 // Trigger process (sample included in next interval).
237 counter.Set(150, kStreamId + 1);
238 // Rate per interval: ((188 - 0) + (100 - 0)) / 2 sec = 144 samples/sec
239 EXPECT_EQ(1, observer->num_calls_);
240 EXPECT_EQ(144, observer->last_sample_);
241 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
242 // Trigger process (sample included in next interval).
243 counter.Set(198, kStreamId);
244 // Rate per interval: (0 + (150 - 100)) / 2 sec = 25 samples/sec
245 EXPECT_EQ(2, observer->num_calls_);
246 EXPECT_EQ(25, observer->last_sample_);
247 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
248 // Trigger process (sample included in next interval).
249 counter.Set(200, kStreamId);
250 // Rate per interval: ((198 - 188) + (0)) / 2 sec = 5 samples/sec
251 EXPECT_EQ(3, observer->num_calls_);
252 EXPECT_EQ(5, observer->last_sample_);
253 // Aggregated stats.
254 AggregatedStats stats = counter.GetStats();
255 EXPECT_EQ(3, stats.num_samples);
256 EXPECT_EQ(5, stats.min);
257 EXPECT_EQ(144, stats.max);
258}
259
asapersson0e9d6d92016-05-23 06:07:55 -0700260TEST_F(StatsCounterTest, TestGetStats_MultipleIntervals) {
asaperssonce2e1362016-09-09 00:13:35 -0700261 AvgCounter counter(&clock_, nullptr, false);
asapersson0e9d6d92016-05-23 06:07:55 -0700262 const int kSample1 = 1;
263 const int kSample2 = 5;
264 const int kSample3 = 8;
265 const int kSample4 = 11;
266 const int kSample5 = 50;
asaperssone402a142016-10-06 23:39:15 -0700267 AddSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
268 AddSampleAndAdvance(kSample2, kDefaultProcessIntervalMs, &counter);
269 AddSampleAndAdvance(kSample3, kDefaultProcessIntervalMs, &counter);
270 AddSampleAndAdvance(kSample4, kDefaultProcessIntervalMs, &counter);
271 AddSampleAndAdvance(kSample5, kDefaultProcessIntervalMs, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -0700272 // Trigger process (sample included in next interval).
273 counter.Add(111);
274 AggregatedStats stats = counter.GetStats();
275 EXPECT_EQ(5, stats.num_samples);
276 EXPECT_EQ(kSample1, stats.min);
277 EXPECT_EQ(kSample5, stats.max);
278 EXPECT_EQ(15, stats.average);
279}
280
281TEST_F(StatsCounterTest, TestGetStatsTwice) {
282 const int kSample1 = 4;
283 const int kSample2 = 7;
asaperssonce2e1362016-09-09 00:13:35 -0700284 AvgCounter counter(&clock_, nullptr, false);
asaperssone402a142016-10-06 23:39:15 -0700285 AddSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -0700286 // Trigger process (sample included in next interval).
287 counter.Add(kSample2);
288 AggregatedStats stats = counter.GetStats();
289 EXPECT_EQ(1, stats.num_samples);
290 EXPECT_EQ(kSample1, stats.min);
291 EXPECT_EQ(kSample1, stats.max);
292 // Trigger process (sample included in next interval).
asaperssone402a142016-10-06 23:39:15 -0700293 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700294 counter.Add(111);
295 stats = counter.GetStats();
296 EXPECT_EQ(2, stats.num_samples);
297 EXPECT_EQ(kSample1, stats.min);
298 EXPECT_EQ(kSample2, stats.max);
299 EXPECT_EQ(6, stats.average);
300}
301
302TEST_F(StatsCounterTest, TestRateAccCounter_NegativeRateIgnored) {
303 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
304 const int kSample1 = 200; // 200 / 2 sec
305 const int kSample2 = 100; // -100 / 2 sec - negative ignored
306 const int kSample3 = 700; // 600 / 2 sec
asapersson5093b382016-08-15 01:20:30 -0700307 RateAccCounter counter(&clock_, observer, true);
asaperssone402a142016-10-06 23:39:15 -0700308 SetSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
309 SetSampleAndAdvance(kSample2, kDefaultProcessIntervalMs, &counter);
310 SetSampleAndAdvance(kSample3, kDefaultProcessIntervalMs, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -0700311 EXPECT_EQ(1, observer->num_calls_);
312 EXPECT_EQ(100, observer->last_sample_);
313 // Trigger process (sample included in next interval).
asaperssonfe647f42016-11-01 00:21:34 -0700314 counter.Set(2000, kStreamId);
asapersson0e9d6d92016-05-23 06:07:55 -0700315 EXPECT_EQ(2, observer->num_calls_);
316 EXPECT_EQ(300, observer->last_sample_);
317 // Aggregated stats.
318 AggregatedStats stats = counter.GetStats();
319 EXPECT_EQ(2, stats.num_samples);
320 EXPECT_EQ(100, stats.min);
321 EXPECT_EQ(300, stats.max);
322 EXPECT_EQ(200, stats.average);
323}
324
asaperssonce2e1362016-09-09 00:13:35 -0700325TEST_F(StatsCounterTest, TestAvgCounter_IntervalsWithoutSamplesIncluded) {
326 // Samples: | 6 | x | x | 8 | // x: empty interval
327 // Stats: | 6 | 6 | 6 | 8 | // x -> last value reported
asapersson0e9d6d92016-05-23 06:07:55 -0700328 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asaperssonce2e1362016-09-09 00:13:35 -0700329 AvgCounter counter(&clock_, observer, true);
asaperssone402a142016-10-06 23:39:15 -0700330 AddSampleAndAdvance(6, kDefaultProcessIntervalMs * 4 - 1, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -0700331 // Trigger process (sample included in next interval).
332 counter.Add(8);
asaperssonce2e1362016-09-09 00:13:35 -0700333 // [6:3], 3 intervals passed (2 without samples -> last value reported).
334 AggregatedStats stats = counter.ProcessAndGetStats();
335 EXPECT_EQ(3, stats.num_samples);
asapersson0e9d6d92016-05-23 06:07:55 -0700336 EXPECT_EQ(6, stats.min);
asaperssonce2e1362016-09-09 00:13:35 -0700337 EXPECT_EQ(6, stats.max);
338 // Make next interval pass and verify stats: [6:3],[8:1]
339 clock_.AdvanceTimeMilliseconds(1);
340 counter.ProcessAndGetStats();
341 EXPECT_EQ(4, observer->num_calls_);
342 EXPECT_EQ(8, observer->last_sample_);
343}
344
345TEST_F(StatsCounterTest, TestAvgCounter_WithPause) {
346 // Samples: | 6 | x | x | x | - | 22 | x | // x: empty interval, -: paused
347 // Stats: | 6 | 6 | 6 | 6 | - | 22 | 22 | // x -> last value reported
348 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
349 AvgCounter counter(&clock_, observer, true);
350 // Add sample and advance 3 intervals (2 w/o samples -> last value reported).
asaperssone402a142016-10-06 23:39:15 -0700351 AddSampleAndAdvance(6, kDefaultProcessIntervalMs * 4 - 1, &counter);
asaperssonce2e1362016-09-09 00:13:35 -0700352 // Trigger process and verify stats: [6:3]
353 counter.ProcessAndGetStats();
354 EXPECT_EQ(3, observer->num_calls_);
355 EXPECT_EQ(6, observer->last_sample_);
356 // Make next interval pass (1 without samples).
357 // Process and pause. Verify stats: [6:4].
358 clock_.AdvanceTimeMilliseconds(1);
359 counter.ProcessAndPause();
360 EXPECT_EQ(4, observer->num_calls_); // Last value reported.
361 EXPECT_EQ(6, observer->last_sample_);
362 // Make next interval pass (1 without samples -> ignored while paused).
asaperssone402a142016-10-06 23:39:15 -0700363 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 2 - 1);
asaperssonce2e1362016-09-09 00:13:35 -0700364 counter.Add(22); // Stops pause.
365 EXPECT_EQ(4, observer->num_calls_);
366 EXPECT_EQ(6, observer->last_sample_);
367 // Make next interval pass, [6:4][22:1]
368 clock_.AdvanceTimeMilliseconds(1);
369 counter.ProcessAndGetStats();
370 EXPECT_EQ(5, observer->num_calls_);
371 EXPECT_EQ(22, observer->last_sample_);
372 // Make 1 interval pass (1 w/o samples -> pause stopped, last value reported).
asaperssone402a142016-10-06 23:39:15 -0700373 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asaperssonce2e1362016-09-09 00:13:35 -0700374 counter.ProcessAndGetStats();
375 EXPECT_EQ(6, observer->num_calls_);
376 EXPECT_EQ(22, observer->last_sample_);
asapersson0e9d6d92016-05-23 06:07:55 -0700377}
378
asapersson93e1e232017-02-06 05:18:35 -0800379TEST_F(StatsCounterTest, TestRateAccCounter_AddSampleStopsPause) {
380 // Samples: | 12 | 24 | // -: paused
381 // Stats: | 6 | 6 |
382 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
383 RateAccCounter counter(&clock_, observer, true);
384 // Add sample and advance 1 intervals.
385 counter.Set(12, kStreamId);
386 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
387 // Trigger process and verify stats: [6:1]
388 counter.ProcessAndPause();
389 EXPECT_EQ(1, observer->num_calls_);
390 EXPECT_EQ(6, observer->last_sample_);
391 // Add sample and advance 1 intervals.
392 counter.Set(24, kStreamId); // Pause stopped.
393 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
394 counter.ProcessAndGetStats();
395 EXPECT_EQ(2, observer->num_calls_);
396 EXPECT_EQ(6, observer->last_sample_);
397}
398
399TEST_F(StatsCounterTest, TestRateAccCounter_AddSameSampleDoesNotStopPause) {
400 // Samples: | 12 | 12 | 24 | // -: paused
401 // Stats: | 6 | - | 6 |
402 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
403 RateAccCounter counter(&clock_, observer, true);
404 // Add sample and advance 1 intervals.
405 counter.Set(12, kStreamId);
406 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
407 // Trigger process and verify stats: [6:1]
408 counter.ProcessAndPause();
409 EXPECT_EQ(1, observer->num_calls_);
410 EXPECT_EQ(6, observer->last_sample_);
411 // Add same sample and advance 1 intervals.
412 counter.Set(12, kStreamId); // Pause not stopped.
413 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
414 counter.ProcessAndGetStats();
415 EXPECT_EQ(1, observer->num_calls_);
416 EXPECT_EQ(6, observer->last_sample_);
417 // Add new sample and advance 1 intervals.
418 counter.Set(24, kStreamId); // Pause stopped.
419 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
420 counter.ProcessAndGetStats();
421 EXPECT_EQ(2, observer->num_calls_);
422 EXPECT_EQ(6, observer->last_sample_);
423}
424
425TEST_F(StatsCounterTest, TestRateAccCounter_PauseAndStopPause) {
426 // Samples: | 12 | 12 | 12 | // -: paused
427 // Stats: | 6 | - | 0 |
428 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
429 RateAccCounter counter(&clock_, observer, true);
430 // Add sample and advance 1 intervals.
431 counter.Set(12, kStreamId);
432 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
433 // Trigger process and verify stats: [6:1]
434 counter.ProcessAndPause();
435 EXPECT_EQ(1, observer->num_calls_);
436 EXPECT_EQ(6, observer->last_sample_);
437 // Add same sample and advance 1 intervals.
438 counter.Set(12, kStreamId); // Pause not stopped.
439 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
440 counter.ProcessAndGetStats();
441 EXPECT_EQ(1, observer->num_calls_);
442 EXPECT_EQ(6, observer->last_sample_);
443 // Stop pause, add sample and advance 1 intervals.
444 counter.ProcessAndStopPause();
445 counter.Set(12, kStreamId);
446 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
447 counter.ProcessAndGetStats();
448 EXPECT_EQ(2, observer->num_calls_);
449 EXPECT_EQ(0, observer->last_sample_);
450}
451
452TEST_F(StatsCounterTest, TestAvgCounter_WithoutMinPauseTimePassed) {
453 // Samples: | 6 | 2 | - | // x: empty interval, -: paused
454 // Stats: | 6 | 2 | - | // x -> last value reported
455 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
456 AvgCounter counter(&clock_, observer, true);
457 // Add sample and advance 1 intervals.
458 AddSampleAndAdvance(6, kDefaultProcessIntervalMs, &counter);
459 // Process and pause. Verify stats: [6:1].
460 const int64_t kMinMs = 500;
461 counter.ProcessAndPauseForDuration(kMinMs);
462 EXPECT_EQ(1, observer->num_calls_); // Last value reported.
463 EXPECT_EQ(6, observer->last_sample_);
464 // Min pause time has not pass.
465 clock_.AdvanceTimeMilliseconds(kMinMs - 1);
466 counter.Add(2); // Pause not stopped.
467 // Make two intervals pass (1 without samples -> ignored while paused).
468 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 2 - (kMinMs - 1));
469 counter.ProcessAndGetStats();
470 EXPECT_EQ(2, observer->num_calls_);
471 EXPECT_EQ(2, observer->last_sample_);
472}
473
474TEST_F(StatsCounterTest, TestAvgCounter_WithMinPauseTimePassed) {
475 // Samples: | 6 | 2 | x | // x: empty interval, -: paused
476 // Stats: | 6 | 2 | 2 | // x -> last value reported
477 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
478 AvgCounter counter(&clock_, observer, true);
479 // Add sample and advance 1 intervals.
480 AddSampleAndAdvance(6, kDefaultProcessIntervalMs, &counter);
481 // Process and pause. Verify stats: [6:1].
482 const int64_t kMinMs = 500;
483 counter.ProcessAndPauseForDuration(kMinMs);
484 EXPECT_EQ(1, observer->num_calls_); // Last value reported.
485 EXPECT_EQ(6, observer->last_sample_);
486 // Make min pause time pass.
487 clock_.AdvanceTimeMilliseconds(kMinMs);
488 counter.Add(2); // Stop pause.
489 // Make two intervals pass (1 without samples -> last value reported).
490 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 2 - kMinMs);
491 counter.ProcessAndGetStats();
492 EXPECT_EQ(3, observer->num_calls_);
493 EXPECT_EQ(2, observer->last_sample_);
494}
495
asapersson5093b382016-08-15 01:20:30 -0700496TEST_F(StatsCounterTest, TestRateCounter_IntervalsWithoutSamplesIgnored) {
asaperssonce2e1362016-09-09 00:13:35 -0700497 // Samples: | 50 | x | 20 | // x: empty interval
498 // Stats: | 25 | x | 10 | // x -> ignored
asapersson5093b382016-08-15 01:20:30 -0700499 const bool kIncludeEmptyIntervals = false;
asapersson0e9d6d92016-05-23 06:07:55 -0700500 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
501 const int kSample1 = 50; // 50 / 2 sec
502 const int kSample2 = 20; // 20 / 2 sec
asapersson5093b382016-08-15 01:20:30 -0700503 RateCounter counter(&clock_, observer, kIncludeEmptyIntervals);
504 counter.Add(kSample1);
asaperssone402a142016-10-06 23:39:15 -0700505 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 3 - 1);
asapersson5093b382016-08-15 01:20:30 -0700506 // Trigger process (sample included in next interval).
507 counter.Add(kSample2);
asaperssonce2e1362016-09-09 00:13:35 -0700508 // [25:1], 2 intervals passed (1 without samples -> ignored).
asapersson5093b382016-08-15 01:20:30 -0700509 EXPECT_EQ(1, observer->num_calls_);
510 EXPECT_EQ(25, observer->last_sample_);
asaperssonce2e1362016-09-09 00:13:35 -0700511 // Make next interval pass and verify stats: [10:1],[25:1]
asapersson5093b382016-08-15 01:20:30 -0700512 clock_.AdvanceTimeMilliseconds(1);
asaperssonce2e1362016-09-09 00:13:35 -0700513 counter.ProcessAndGetStats();
asapersson5093b382016-08-15 01:20:30 -0700514 EXPECT_EQ(2, observer->num_calls_);
515 EXPECT_EQ(10, observer->last_sample_);
asapersson5093b382016-08-15 01:20:30 -0700516}
517
518TEST_F(StatsCounterTest, TestRateCounter_IntervalsWithoutSamplesIncluded) {
asaperssonce2e1362016-09-09 00:13:35 -0700519 // Samples: | 50 | x | 20 | // x: empty interval
520 // Stats: | 25 | 0 | 10 | // x -> zero reported
asapersson5093b382016-08-15 01:20:30 -0700521 const bool kIncludeEmptyIntervals = true;
522 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
523 const int kSample1 = 50; // 50 / 2 sec
524 const int kSample2 = 20; // 20 / 2 sec
525 RateCounter counter(&clock_, observer, kIncludeEmptyIntervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700526 counter.Add(kSample1);
asaperssone402a142016-10-06 23:39:15 -0700527 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 3 - 1);
asapersson0e9d6d92016-05-23 06:07:55 -0700528 // Trigger process (sample included in next interval).
529 counter.Add(kSample2);
asaperssonce2e1362016-09-09 00:13:35 -0700530 // [0:1],[25:1], 2 intervals passed (1 without samples -> zero reported).
asapersson0e9d6d92016-05-23 06:07:55 -0700531 EXPECT_EQ(2, observer->num_calls_);
asaperssonce2e1362016-09-09 00:13:35 -0700532 EXPECT_EQ(0, observer->last_sample_);
533 // Make last interval pass and verify stats: [0:1],[10:1],[25:1]
asapersson0e9d6d92016-05-23 06:07:55 -0700534 clock_.AdvanceTimeMilliseconds(1);
asaperssonce2e1362016-09-09 00:13:35 -0700535 AggregatedStats stats = counter.ProcessAndGetStats();
536 EXPECT_EQ(25, stats.max);
asapersson0e9d6d92016-05-23 06:07:55 -0700537 EXPECT_EQ(3, observer->num_calls_);
538 EXPECT_EQ(10, observer->last_sample_);
asaperssonce2e1362016-09-09 00:13:35 -0700539}
540
541TEST_F(StatsCounterTest, TestRateAccCounter_IntervalsWithoutSamplesIncluded) {
542 // Samples: | 12 | x | x | x | 60 | // x: empty interval
543 // Stats: | 6 | 0 | 0 | 0 | 24 | // x -> zero reported
544 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
545 RateAccCounter counter(&clock_, observer, true);
546 VerifyStatsIsNotSet(counter.ProcessAndGetStats());
547 // Advance one interval and verify stats.
asaperssone402a142016-10-06 23:39:15 -0700548 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asaperssonce2e1362016-09-09 00:13:35 -0700549 VerifyStatsIsNotSet(counter.ProcessAndGetStats());
550 // Add sample and advance 3 intervals (2 w/o samples -> zero reported).
asaperssonfe647f42016-11-01 00:21:34 -0700551 counter.Set(12, kStreamId);
asaperssone402a142016-10-06 23:39:15 -0700552 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 4 - 1);
asaperssonce2e1362016-09-09 00:13:35 -0700553 // Trigger process and verify stats: [0:2][6:1]
554 counter.ProcessAndGetStats();
555 EXPECT_EQ(3, observer->num_calls_);
556 EXPECT_EQ(0, observer->last_sample_);
557 // Make next interval pass (1 w/o samples -> zero reported), [0:3][6:1]
558 clock_.AdvanceTimeMilliseconds(1);
559 counter.ProcessAndGetStats();
560 EXPECT_EQ(4, observer->num_calls_);
561 EXPECT_EQ(0, observer->last_sample_);
562 // Insert sample and advance non-complete interval, no change, [0:3][6:1]
asaperssone402a142016-10-06 23:39:15 -0700563 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
asaperssonfe647f42016-11-01 00:21:34 -0700564 counter.Set(60, kStreamId);
asaperssonce2e1362016-09-09 00:13:35 -0700565 EXPECT_EQ(4, observer->num_calls_);
566 // Make next interval pass, [0:3][6:1][24:1]
567 clock_.AdvanceTimeMilliseconds(1);
568 AggregatedStats stats = counter.ProcessAndGetStats();
569 EXPECT_EQ(5, observer->num_calls_);
570 EXPECT_EQ(24, observer->last_sample_);
571 EXPECT_EQ(6, stats.average);
572}
573
574TEST_F(StatsCounterTest, TestRateAccCounter_IntervalsWithoutSamplesIgnored) {
575 // Samples: | 12 | x | x | x | 60 | // x: empty interval
576 // Stats: | 6 | x | x | x | 24 | // x -> ignored
577 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
578 RateAccCounter counter(&clock_, observer, false);
579 // Add sample and advance 3 intervals (2 w/o samples -> ignored).
asaperssonfe647f42016-11-01 00:21:34 -0700580 counter.Set(12, kStreamId);
asaperssone402a142016-10-06 23:39:15 -0700581 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 4 - 1);
asaperssonce2e1362016-09-09 00:13:35 -0700582 // Trigger process and verify stats: [6:1]
583 counter.ProcessAndGetStats();
584 EXPECT_EQ(1, observer->num_calls_);
585 EXPECT_EQ(6, observer->last_sample_);
586 // Make next interval pass (1 w/o samples -> ignored), [6:1]
587 clock_.AdvanceTimeMilliseconds(1);
588 counter.ProcessAndGetStats();
589 EXPECT_EQ(1, observer->num_calls_);
590 // Insert sample and advance non-complete interval, no change, [6:1]
asaperssone402a142016-10-06 23:39:15 -0700591 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
asaperssonfe647f42016-11-01 00:21:34 -0700592 counter.Set(60, kStreamId);
asaperssonce2e1362016-09-09 00:13:35 -0700593 counter.ProcessAndGetStats();
594 EXPECT_EQ(1, observer->num_calls_);
595 // Make next interval pass, [6:1][24:1]
596 clock_.AdvanceTimeMilliseconds(1);
597 counter.ProcessAndGetStats();
598 EXPECT_EQ(2, observer->num_calls_);
599 EXPECT_EQ(24, observer->last_sample_);
asapersson0e9d6d92016-05-23 06:07:55 -0700600}
601
602} // namespace webrtc