1 /*
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 
11 #include "video/stats_counter.h"
12 
13 #include "system_wrappers/include/clock.h"
14 #include "test/gtest.h"
15 
16 namespace webrtc {
17 namespace {
18 const int kDefaultProcessIntervalMs = 2000;
19 const uint32_t kStreamId = 123456;
20 
21 class StatsCounterObserverImpl : public StatsCounterObserver {
22  public:
StatsCounterObserverImpl()23   StatsCounterObserverImpl() : num_calls_(0), last_sample_(-1) {}
OnMetricUpdated(int sample)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 
33 class StatsCounterTest : public ::testing::Test {
34  protected:
StatsCounterTest()35   StatsCounterTest() : clock_(1234) {}
36 
AddSampleAndAdvance(int sample,int interval_ms,AvgCounter * counter)37   void AddSampleAndAdvance(int sample, int interval_ms, AvgCounter* counter) {
38     counter->Add(sample);
39     clock_.AdvanceTimeMilliseconds(interval_ms);
40   }
41 
SetSampleAndAdvance(int sample,int interval_ms,RateAccCounter * counter)42   void SetSampleAndAdvance(int sample,
43                            int interval_ms,
44                            RateAccCounter* counter) {
45     counter->Set(sample, kStreamId);
46     clock_.AdvanceTimeMilliseconds(interval_ms);
47   }
48 
VerifyStatsIsNotSet(const AggregatedStats & stats)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 
TEST_F(StatsCounterTest,NoSamples)59 TEST_F(StatsCounterTest, NoSamples) {
60   AvgCounter counter(&clock_, nullptr, false);
61   VerifyStatsIsNotSet(counter.GetStats());
62 }
63 
TEST_F(StatsCounterTest,TestRegisterObserver)64 TEST_F(StatsCounterTest, TestRegisterObserver) {
65   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
66   const int kSample = 22;
67   AvgCounter counter(&clock_, observer, false);
68   AddSampleAndAdvance(kSample, kDefaultProcessIntervalMs, &counter);
69   // Trigger process (sample included in next interval).
70   counter.Add(111);
71   EXPECT_EQ(1, observer->num_calls_);
72 }
73 
TEST_F(StatsCounterTest,HasSample)74 TEST_F(StatsCounterTest, HasSample) {
75   AvgCounter counter(&clock_, nullptr, false);
76   EXPECT_FALSE(counter.HasSample());
77   counter.Add(1);
78   EXPECT_TRUE(counter.HasSample());
79 }
80 
TEST_F(StatsCounterTest,VerifyProcessInterval)81 TEST_F(StatsCounterTest, VerifyProcessInterval) {
82   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
83   AvgCounter counter(&clock_, observer, false);
84   counter.Add(4);
85   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
86   // 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 
TEST_F(StatsCounterTest,TestMetric_AvgCounter)101 TEST_F(StatsCounterTest, TestMetric_AvgCounter) {
102   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
103   AvgCounter counter(&clock_, observer, false);
104   counter.Add(4);
105   counter.Add(8);
106   counter.Add(9);
107   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
108   // 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 
TEST_F(StatsCounterTest,TestMetric_MaxCounter)121 TEST_F(StatsCounterTest, TestMetric_MaxCounter) {
122   const int64_t kProcessIntervalMs = 1000;
123   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
124   MaxCounter counter(&clock_, observer, kProcessIntervalMs);
125   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 
TEST_F(StatsCounterTest,TestMetric_PercentCounter)142 TEST_F(StatsCounterTest, TestMetric_PercentCounter) {
143   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
144   PercentCounter counter(&clock_, observer);
145   counter.Add(true);
146   counter.Add(false);
147   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
148   // 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 
TEST_F(StatsCounterTest,TestMetric_PermilleCounter)160 TEST_F(StatsCounterTest, TestMetric_PermilleCounter) {
161   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
162   PermilleCounter counter(&clock_, observer);
163   counter.Add(true);
164   counter.Add(false);
165   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
166   // 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 
TEST_F(StatsCounterTest,TestMetric_RateCounter)178 TEST_F(StatsCounterTest, TestMetric_RateCounter) {
179   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
180   RateCounter counter(&clock_, observer, true);
181   counter.Add(186);
182   counter.Add(350);
183   counter.Add(22);
184   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
185   // 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 
TEST_F(StatsCounterTest,TestMetric_RateAccCounter)197 TEST_F(StatsCounterTest, TestMetric_RateAccCounter) {
198   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
199   RateAccCounter counter(&clock_, observer, true);
200   counter.Set(175, kStreamId);
201   counter.Set(188, kStreamId);
202   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
203   // Trigger process (sample included in next interval).
204   counter.Set(192, kStreamId);
205   // 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 
TEST_F(StatsCounterTest,TestMetric_RateAccCounterWithSetLast)215 TEST_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 
TEST_F(StatsCounterTest,TestMetric_RateAccCounterWithMultipleStreamIds)229 TEST_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 
TEST_F(StatsCounterTest,TestGetStats_MultipleIntervals)260 TEST_F(StatsCounterTest, TestGetStats_MultipleIntervals) {
261   AvgCounter counter(&clock_, nullptr, false);
262   const int kSample1 = 1;
263   const int kSample2 = 5;
264   const int kSample3 = 8;
265   const int kSample4 = 11;
266   const int kSample5 = 50;
267   AddSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
268   AddSampleAndAdvance(kSample2, kDefaultProcessIntervalMs, &counter);
269   AddSampleAndAdvance(kSample3, kDefaultProcessIntervalMs, &counter);
270   AddSampleAndAdvance(kSample4, kDefaultProcessIntervalMs, &counter);
271   AddSampleAndAdvance(kSample5, kDefaultProcessIntervalMs, &counter);
272   // 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 
TEST_F(StatsCounterTest,TestGetStatsTwice)281 TEST_F(StatsCounterTest, TestGetStatsTwice) {
282   const int kSample1 = 4;
283   const int kSample2 = 7;
284   AvgCounter counter(&clock_, nullptr, false);
285   AddSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
286   // 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).
293   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
294   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 
TEST_F(StatsCounterTest,TestRateAccCounter_NegativeRateIgnored)302 TEST_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
307   RateAccCounter counter(&clock_, observer, true);
308   SetSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
309   SetSampleAndAdvance(kSample2, kDefaultProcessIntervalMs, &counter);
310   SetSampleAndAdvance(kSample3, kDefaultProcessIntervalMs, &counter);
311   EXPECT_EQ(1, observer->num_calls_);
312   EXPECT_EQ(100, observer->last_sample_);
313   // Trigger process (sample included in next interval).
314   counter.Set(2000, kStreamId);
315   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 
TEST_F(StatsCounterTest,TestAvgCounter_IntervalsWithoutSamplesIncluded)325 TEST_F(StatsCounterTest, TestAvgCounter_IntervalsWithoutSamplesIncluded) {
326   // Samples: | 6 | x | x | 8 |  // x: empty interval
327   // Stats:   | 6 | 6 | 6 | 8 |  // x -> last value reported
328   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
329   AvgCounter counter(&clock_, observer, true);
330   AddSampleAndAdvance(6, kDefaultProcessIntervalMs * 4 - 1, &counter);
331   // Trigger process (sample included in next interval).
332   counter.Add(8);
333   // [6:3], 3 intervals passed (2 without samples -> last value reported).
334   AggregatedStats stats = counter.ProcessAndGetStats();
335   EXPECT_EQ(3, stats.num_samples);
336   EXPECT_EQ(6, stats.min);
337   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 
TEST_F(StatsCounterTest,TestAvgCounter_WithPause)345 TEST_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).
351   AddSampleAndAdvance(6, kDefaultProcessIntervalMs * 4 - 1, &counter);
352   // 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).
363   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 2 - 1);
364   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).
373   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
374   counter.ProcessAndGetStats();
375   EXPECT_EQ(6, observer->num_calls_);
376   EXPECT_EQ(22, observer->last_sample_);
377 }
378 
TEST_F(StatsCounterTest,TestRateAccCounter_AddSampleStopsPause)379 TEST_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 
TEST_F(StatsCounterTest,TestRateAccCounter_AddSameSampleDoesNotStopPause)399 TEST_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 
TEST_F(StatsCounterTest,TestRateAccCounter_PauseAndStopPause)425 TEST_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 
TEST_F(StatsCounterTest,TestAvgCounter_WithoutMinPauseTimePassed)452 TEST_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 
TEST_F(StatsCounterTest,TestAvgCounter_WithMinPauseTimePassed)474 TEST_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 
TEST_F(StatsCounterTest,TestRateCounter_IntervalsWithoutSamplesIgnored)496 TEST_F(StatsCounterTest, TestRateCounter_IntervalsWithoutSamplesIgnored) {
497   // Samples: | 50 | x | 20 |  // x: empty interval
498   // Stats:   | 25 | x | 10 |  // x -> ignored
499   const bool kIncludeEmptyIntervals = false;
500   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
501   const int kSample1 = 50;  //  50 / 2 sec
502   const int kSample2 = 20;  //  20 / 2 sec
503   RateCounter counter(&clock_, observer, kIncludeEmptyIntervals);
504   counter.Add(kSample1);
505   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 3 - 1);
506   // Trigger process (sample included in next interval).
507   counter.Add(kSample2);
508   // [25:1], 2 intervals passed (1 without samples -> ignored).
509   EXPECT_EQ(1, observer->num_calls_);
510   EXPECT_EQ(25, observer->last_sample_);
511   // Make next interval pass and verify stats: [10:1],[25:1]
512   clock_.AdvanceTimeMilliseconds(1);
513   counter.ProcessAndGetStats();
514   EXPECT_EQ(2, observer->num_calls_);
515   EXPECT_EQ(10, observer->last_sample_);
516 }
517 
TEST_F(StatsCounterTest,TestRateCounter_IntervalsWithoutSamplesIncluded)518 TEST_F(StatsCounterTest, TestRateCounter_IntervalsWithoutSamplesIncluded) {
519   // Samples: | 50 | x | 20 |  // x: empty interval
520   // Stats:   | 25 | 0 | 10 |  // x -> zero reported
521   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);
526   counter.Add(kSample1);
527   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 3 - 1);
528   // Trigger process (sample included in next interval).
529   counter.Add(kSample2);
530   // [0:1],[25:1], 2 intervals passed (1 without samples -> zero reported).
531   EXPECT_EQ(2, observer->num_calls_);
532   EXPECT_EQ(0, observer->last_sample_);
533   // Make last interval pass and verify stats: [0:1],[10:1],[25:1]
534   clock_.AdvanceTimeMilliseconds(1);
535   AggregatedStats stats = counter.ProcessAndGetStats();
536   EXPECT_EQ(25, stats.max);
537   EXPECT_EQ(3, observer->num_calls_);
538   EXPECT_EQ(10, observer->last_sample_);
539 }
540 
TEST_F(StatsCounterTest,TestRateAccCounter_IntervalsWithoutSamplesIncluded)541 TEST_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.
548   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
549   VerifyStatsIsNotSet(counter.ProcessAndGetStats());
550   // Add sample and advance 3 intervals (2 w/o samples -> zero reported).
551   counter.Set(12, kStreamId);
552   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 4 - 1);
553   // 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]
563   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
564   counter.Set(60, kStreamId);
565   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 
TEST_F(StatsCounterTest,TestRateAccCounter_IntervalsWithoutSamplesIgnored)574 TEST_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).
580   counter.Set(12, kStreamId);
581   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 4 - 1);
582   // 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]
591   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
592   counter.Set(60, kStreamId);
593   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_);
600 }
601 
602 }  // namespace webrtc
603