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()
36       : clock_(1234) {}
37 
AddSampleAndAdvance(int sample,int interval_ms,AvgCounter * counter)38   void AddSampleAndAdvance(int sample, int interval_ms, AvgCounter* counter) {
39     counter->Add(sample);
40     clock_.AdvanceTimeMilliseconds(interval_ms);
41   }
42 
SetSampleAndAdvance(int sample,int interval_ms,RateAccCounter * counter)43   void SetSampleAndAdvance(int sample,
44                            int interval_ms,
45                            RateAccCounter* counter) {
46     counter->Set(sample, kStreamId);
47     clock_.AdvanceTimeMilliseconds(interval_ms);
48   }
49 
VerifyStatsIsNotSet(const AggregatedStats & stats)50   void VerifyStatsIsNotSet(const AggregatedStats& stats) {
51     EXPECT_EQ(0, stats.num_samples);
52     EXPECT_EQ(-1, stats.min);
53     EXPECT_EQ(-1, stats.max);
54     EXPECT_EQ(-1, stats.average);
55   }
56 
57   SimulatedClock clock_;
58 };
59 
TEST_F(StatsCounterTest,NoSamples)60 TEST_F(StatsCounterTest, NoSamples) {
61   AvgCounter counter(&clock_, nullptr, false);
62   VerifyStatsIsNotSet(counter.GetStats());
63 }
64 
TEST_F(StatsCounterTest,TestRegisterObserver)65 TEST_F(StatsCounterTest, TestRegisterObserver) {
66   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
67   const int kSample = 22;
68   AvgCounter counter(&clock_, observer, false);
69   AddSampleAndAdvance(kSample, kDefaultProcessIntervalMs, &counter);
70   // Trigger process (sample included in next interval).
71   counter.Add(111);
72   EXPECT_EQ(1, observer->num_calls_);
73 }
74 
TEST_F(StatsCounterTest,HasSample)75 TEST_F(StatsCounterTest, HasSample) {
76   AvgCounter counter(&clock_, nullptr, false);
77   EXPECT_FALSE(counter.HasSample());
78   counter.Add(1);
79   EXPECT_TRUE(counter.HasSample());
80 }
81 
TEST_F(StatsCounterTest,VerifyProcessInterval)82 TEST_F(StatsCounterTest, VerifyProcessInterval) {
83   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
84   AvgCounter counter(&clock_, observer, false);
85   counter.Add(4);
86   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
87   // Try trigger process (interval has not passed).
88   counter.Add(8);
89   EXPECT_EQ(0, observer->num_calls_);
90   VerifyStatsIsNotSet(counter.GetStats());
91   // Make process interval pass.
92   clock_.AdvanceTimeMilliseconds(1);
93   // Trigger process (sample included in next interval).
94   counter.Add(111);
95   EXPECT_EQ(1, observer->num_calls_);
96   EXPECT_EQ(6, observer->last_sample_);
97   // Aggregated stats.
98   AggregatedStats stats = counter.GetStats();
99   EXPECT_EQ(1, stats.num_samples);
100 }
101 
TEST_F(StatsCounterTest,TestMetric_AvgCounter)102 TEST_F(StatsCounterTest, TestMetric_AvgCounter) {
103   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
104   AvgCounter counter(&clock_, observer, false);
105   counter.Add(4);
106   counter.Add(8);
107   counter.Add(9);
108   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
109   // Trigger process (sample included in next interval).
110   counter.Add(111);
111   // Average per interval.
112   EXPECT_EQ(1, observer->num_calls_);
113   EXPECT_EQ(7, observer->last_sample_);
114   // Aggregated stats.
115   AggregatedStats stats = counter.GetStats();
116   EXPECT_EQ(1, stats.num_samples);
117   EXPECT_EQ(7, stats.min);
118   EXPECT_EQ(7, stats.max);
119   EXPECT_EQ(7, stats.average);
120 }
121 
TEST_F(StatsCounterTest,TestMetric_MaxCounter)122 TEST_F(StatsCounterTest, TestMetric_MaxCounter) {
123   const int64_t kProcessIntervalMs = 1000;
124   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
125   MaxCounter counter(&clock_, observer, kProcessIntervalMs);
126   counter.Add(4);
127   counter.Add(9);
128   counter.Add(8);
129   clock_.AdvanceTimeMilliseconds(kProcessIntervalMs);
130   // Trigger process (sample included in next interval).
131   counter.Add(111);
132   // Average per interval.
133   EXPECT_EQ(1, observer->num_calls_);
134   EXPECT_EQ(9, observer->last_sample_);
135   // Aggregated stats.
136   AggregatedStats stats = counter.GetStats();
137   EXPECT_EQ(1, stats.num_samples);
138   EXPECT_EQ(9, stats.min);
139   EXPECT_EQ(9, stats.max);
140   EXPECT_EQ(9, stats.average);
141 }
142 
TEST_F(StatsCounterTest,TestMetric_PercentCounter)143 TEST_F(StatsCounterTest, TestMetric_PercentCounter) {
144   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
145   PercentCounter counter(&clock_, observer);
146   counter.Add(true);
147   counter.Add(false);
148   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
149   // Trigger process (sample included in next interval).
150   counter.Add(false);
151   // Percentage per interval.
152   EXPECT_EQ(1, observer->num_calls_);
153   EXPECT_EQ(50, observer->last_sample_);
154   // Aggregated stats.
155   AggregatedStats stats = counter.GetStats();
156   EXPECT_EQ(1, stats.num_samples);
157   EXPECT_EQ(50, stats.min);
158   EXPECT_EQ(50, stats.max);
159 }
160 
TEST_F(StatsCounterTest,TestMetric_PermilleCounter)161 TEST_F(StatsCounterTest, TestMetric_PermilleCounter) {
162   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
163   PermilleCounter counter(&clock_, observer);
164   counter.Add(true);
165   counter.Add(false);
166   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
167   // Trigger process (sample included in next interval).
168   counter.Add(false);
169   // Permille per interval.
170   EXPECT_EQ(1, observer->num_calls_);
171   EXPECT_EQ(500, observer->last_sample_);
172   // Aggregated stats.
173   AggregatedStats stats = counter.GetStats();
174   EXPECT_EQ(1, stats.num_samples);
175   EXPECT_EQ(500, stats.min);
176   EXPECT_EQ(500, stats.max);
177 }
178 
TEST_F(StatsCounterTest,TestMetric_RateCounter)179 TEST_F(StatsCounterTest, TestMetric_RateCounter) {
180   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
181   RateCounter counter(&clock_, observer, true);
182   counter.Add(186);
183   counter.Add(350);
184   counter.Add(22);
185   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
186   // Trigger process (sample included in next interval).
187   counter.Add(111);
188   // Rate per interval, (186 + 350 + 22) / 2 sec = 279 samples/sec
189   EXPECT_EQ(1, observer->num_calls_);
190   EXPECT_EQ(279, observer->last_sample_);
191   // Aggregated stats.
192   AggregatedStats stats = counter.GetStats();
193   EXPECT_EQ(1, stats.num_samples);
194   EXPECT_EQ(279, stats.min);
195   EXPECT_EQ(279, stats.max);
196 }
197 
TEST_F(StatsCounterTest,TestMetric_RateAccCounter)198 TEST_F(StatsCounterTest, TestMetric_RateAccCounter) {
199   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
200   RateAccCounter counter(&clock_, observer, true);
201   counter.Set(175, kStreamId);
202   counter.Set(188, kStreamId);
203   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
204   // Trigger process (sample included in next interval).
205   counter.Set(192, kStreamId);
206   // Rate per interval: (188 - 0) / 2 sec = 94 samples/sec
207   EXPECT_EQ(1, observer->num_calls_);
208   EXPECT_EQ(94, observer->last_sample_);
209   // Aggregated stats.
210   AggregatedStats stats = counter.GetStats();
211   EXPECT_EQ(1, stats.num_samples);
212   EXPECT_EQ(94, stats.min);
213   EXPECT_EQ(94, stats.max);
214 }
215 
TEST_F(StatsCounterTest,TestMetric_RateAccCounterWithSetLast)216 TEST_F(StatsCounterTest, TestMetric_RateAccCounterWithSetLast) {
217   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
218   RateAccCounter counter(&clock_, observer, true);
219   counter.SetLast(98, kStreamId);
220   counter.Set(175, kStreamId);
221   counter.Set(188, kStreamId);
222   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
223   // Trigger process (sample included in next interval).
224   counter.Set(192, kStreamId);
225   // Rate per interval: (188 - 98) / 2 sec = 45 samples/sec
226   EXPECT_EQ(1, observer->num_calls_);
227   EXPECT_EQ(45, observer->last_sample_);
228 }
229 
TEST_F(StatsCounterTest,TestMetric_RateAccCounterWithMultipleStreamIds)230 TEST_F(StatsCounterTest, TestMetric_RateAccCounterWithMultipleStreamIds) {
231   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
232   RateAccCounter counter(&clock_, observer, true);
233   counter.Set(175, kStreamId);
234   counter.Set(188, kStreamId);
235   counter.Set(100, kStreamId + 1);
236   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
237   // Trigger process (sample included in next interval).
238   counter.Set(150, kStreamId + 1);
239   // Rate per interval: ((188 - 0) + (100 - 0)) / 2 sec = 144 samples/sec
240   EXPECT_EQ(1, observer->num_calls_);
241   EXPECT_EQ(144, observer->last_sample_);
242   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
243   // Trigger process (sample included in next interval).
244   counter.Set(198, kStreamId);
245   // Rate per interval: (0 + (150 - 100)) / 2 sec = 25 samples/sec
246   EXPECT_EQ(2, observer->num_calls_);
247   EXPECT_EQ(25, observer->last_sample_);
248   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
249   // Trigger process (sample included in next interval).
250   counter.Set(200, kStreamId);
251   // Rate per interval: ((198 - 188) + (0)) / 2 sec = 5 samples/sec
252   EXPECT_EQ(3, observer->num_calls_);
253   EXPECT_EQ(5, observer->last_sample_);
254   // Aggregated stats.
255   AggregatedStats stats = counter.GetStats();
256   EXPECT_EQ(3, stats.num_samples);
257   EXPECT_EQ(5, stats.min);
258   EXPECT_EQ(144, stats.max);
259 }
260 
TEST_F(StatsCounterTest,TestGetStats_MultipleIntervals)261 TEST_F(StatsCounterTest, TestGetStats_MultipleIntervals) {
262   AvgCounter counter(&clock_, nullptr, false);
263   const int kSample1 = 1;
264   const int kSample2 = 5;
265   const int kSample3 = 8;
266   const int kSample4 = 11;
267   const int kSample5 = 50;
268   AddSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
269   AddSampleAndAdvance(kSample2, kDefaultProcessIntervalMs, &counter);
270   AddSampleAndAdvance(kSample3, kDefaultProcessIntervalMs, &counter);
271   AddSampleAndAdvance(kSample4, kDefaultProcessIntervalMs, &counter);
272   AddSampleAndAdvance(kSample5, kDefaultProcessIntervalMs, &counter);
273   // Trigger process (sample included in next interval).
274   counter.Add(111);
275   AggregatedStats stats = counter.GetStats();
276   EXPECT_EQ(5, stats.num_samples);
277   EXPECT_EQ(kSample1, stats.min);
278   EXPECT_EQ(kSample5, stats.max);
279   EXPECT_EQ(15, stats.average);
280 }
281 
TEST_F(StatsCounterTest,TestGetStatsTwice)282 TEST_F(StatsCounterTest, TestGetStatsTwice) {
283   const int kSample1 = 4;
284   const int kSample2 = 7;
285   AvgCounter counter(&clock_, nullptr, false);
286   AddSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
287   // Trigger process (sample included in next interval).
288   counter.Add(kSample2);
289   AggregatedStats stats = counter.GetStats();
290   EXPECT_EQ(1, stats.num_samples);
291   EXPECT_EQ(kSample1, stats.min);
292   EXPECT_EQ(kSample1, stats.max);
293   // Trigger process (sample included in next interval).
294   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
295   counter.Add(111);
296   stats = counter.GetStats();
297   EXPECT_EQ(2, stats.num_samples);
298   EXPECT_EQ(kSample1, stats.min);
299   EXPECT_EQ(kSample2, stats.max);
300   EXPECT_EQ(6, stats.average);
301 }
302 
TEST_F(StatsCounterTest,TestRateAccCounter_NegativeRateIgnored)303 TEST_F(StatsCounterTest, TestRateAccCounter_NegativeRateIgnored) {
304   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
305   const int kSample1 = 200;  //  200 / 2 sec
306   const int kSample2 = 100;  // -100 / 2 sec - negative ignored
307   const int kSample3 = 700;  //  600 / 2 sec
308   RateAccCounter counter(&clock_, observer, true);
309   SetSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
310   SetSampleAndAdvance(kSample2, kDefaultProcessIntervalMs, &counter);
311   SetSampleAndAdvance(kSample3, kDefaultProcessIntervalMs, &counter);
312   EXPECT_EQ(1, observer->num_calls_);
313   EXPECT_EQ(100, observer->last_sample_);
314   // Trigger process (sample included in next interval).
315   counter.Set(2000, kStreamId);
316   EXPECT_EQ(2, observer->num_calls_);
317   EXPECT_EQ(300, observer->last_sample_);
318   // Aggregated stats.
319   AggregatedStats stats = counter.GetStats();
320   EXPECT_EQ(2, stats.num_samples);
321   EXPECT_EQ(100, stats.min);
322   EXPECT_EQ(300, stats.max);
323   EXPECT_EQ(200, stats.average);
324 }
325 
TEST_F(StatsCounterTest,TestAvgCounter_IntervalsWithoutSamplesIncluded)326 TEST_F(StatsCounterTest, TestAvgCounter_IntervalsWithoutSamplesIncluded) {
327   // Samples: | 6 | x | x | 8 |  // x: empty interval
328   // Stats:   | 6 | 6 | 6 | 8 |  // x -> last value reported
329   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
330   AvgCounter counter(&clock_, observer, true);
331   AddSampleAndAdvance(6, kDefaultProcessIntervalMs * 4 - 1, &counter);
332   // Trigger process (sample included in next interval).
333   counter.Add(8);
334   // [6:3], 3 intervals passed (2 without samples -> last value reported).
335   AggregatedStats stats = counter.ProcessAndGetStats();
336   EXPECT_EQ(3, stats.num_samples);
337   EXPECT_EQ(6, stats.min);
338   EXPECT_EQ(6, stats.max);
339   // Make next interval pass and verify stats: [6:3],[8:1]
340   clock_.AdvanceTimeMilliseconds(1);
341   counter.ProcessAndGetStats();
342   EXPECT_EQ(4, observer->num_calls_);
343   EXPECT_EQ(8, observer->last_sample_);
344 }
345 
TEST_F(StatsCounterTest,TestAvgCounter_WithPause)346 TEST_F(StatsCounterTest, TestAvgCounter_WithPause) {
347   // Samples: | 6 | x | x | x | - | 22 | x  |  // x: empty interval, -: paused
348   // Stats:   | 6 | 6 | 6 | 6 | - | 22 | 22 |  // x -> last value reported
349   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
350   AvgCounter counter(&clock_, observer, true);
351   // Add sample and advance 3 intervals (2 w/o samples -> last value reported).
352   AddSampleAndAdvance(6, kDefaultProcessIntervalMs * 4 - 1, &counter);
353   // Trigger process and verify stats: [6:3]
354   counter.ProcessAndGetStats();
355   EXPECT_EQ(3, observer->num_calls_);
356   EXPECT_EQ(6, observer->last_sample_);
357   // Make next interval pass (1 without samples).
358   // Process and pause. Verify stats: [6:4].
359   clock_.AdvanceTimeMilliseconds(1);
360   counter.ProcessAndPause();
361   EXPECT_EQ(4, observer->num_calls_);  // Last value reported.
362   EXPECT_EQ(6, observer->last_sample_);
363   // Make next interval pass (1 without samples -> ignored while paused).
364   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 2 - 1);
365   counter.Add(22);  // Stops pause.
366   EXPECT_EQ(4, observer->num_calls_);
367   EXPECT_EQ(6, observer->last_sample_);
368   // Make next interval pass, [6:4][22:1]
369   clock_.AdvanceTimeMilliseconds(1);
370   counter.ProcessAndGetStats();
371   EXPECT_EQ(5, observer->num_calls_);
372   EXPECT_EQ(22, observer->last_sample_);
373   // Make 1 interval pass (1 w/o samples -> pause stopped, last value reported).
374   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
375   counter.ProcessAndGetStats();
376   EXPECT_EQ(6, observer->num_calls_);
377   EXPECT_EQ(22, observer->last_sample_);
378 }
379 
TEST_F(StatsCounterTest,TestRateAccCounter_AddSampleStopsPause)380 TEST_F(StatsCounterTest, TestRateAccCounter_AddSampleStopsPause) {
381   // Samples: | 12 | 24 |  // -: paused
382   // Stats:   | 6  | 6  |
383   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
384   RateAccCounter counter(&clock_, observer, true);
385   // Add sample and advance 1 intervals.
386   counter.Set(12, kStreamId);
387   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
388   // Trigger process and verify stats: [6:1]
389   counter.ProcessAndPause();
390   EXPECT_EQ(1, observer->num_calls_);
391   EXPECT_EQ(6, observer->last_sample_);
392   // Add sample and advance 1 intervals.
393   counter.Set(24, kStreamId);  // Pause stopped.
394   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
395   counter.ProcessAndGetStats();
396   EXPECT_EQ(2, observer->num_calls_);
397   EXPECT_EQ(6, observer->last_sample_);
398 }
399 
TEST_F(StatsCounterTest,TestRateAccCounter_AddSameSampleDoesNotStopPause)400 TEST_F(StatsCounterTest, TestRateAccCounter_AddSameSampleDoesNotStopPause) {
401   // Samples: | 12 | 12 | 24 |  // -: paused
402   // Stats:   | 6  | -  | 6  |
403   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
404   RateAccCounter counter(&clock_, observer, true);
405   // Add sample and advance 1 intervals.
406   counter.Set(12, kStreamId);
407   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
408   // Trigger process and verify stats: [6:1]
409   counter.ProcessAndPause();
410   EXPECT_EQ(1, observer->num_calls_);
411   EXPECT_EQ(6, observer->last_sample_);
412   // Add same sample and advance 1 intervals.
413   counter.Set(12, kStreamId);  // Pause not stopped.
414   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
415   counter.ProcessAndGetStats();
416   EXPECT_EQ(1, observer->num_calls_);
417   EXPECT_EQ(6, observer->last_sample_);
418   // Add new sample and advance 1 intervals.
419   counter.Set(24, kStreamId);  // Pause stopped.
420   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
421   counter.ProcessAndGetStats();
422   EXPECT_EQ(2, observer->num_calls_);
423   EXPECT_EQ(6, observer->last_sample_);
424 }
425 
TEST_F(StatsCounterTest,TestRateAccCounter_PauseAndStopPause)426 TEST_F(StatsCounterTest, TestRateAccCounter_PauseAndStopPause) {
427   // Samples: | 12 | 12 | 12 |  // -: paused
428   // Stats:   | 6  | -  | 0  |
429   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
430   RateAccCounter counter(&clock_, observer, true);
431   // Add sample and advance 1 intervals.
432   counter.Set(12, kStreamId);
433   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
434   // Trigger process and verify stats: [6:1]
435   counter.ProcessAndPause();
436   EXPECT_EQ(1, observer->num_calls_);
437   EXPECT_EQ(6, observer->last_sample_);
438   // Add same sample and advance 1 intervals.
439   counter.Set(12, kStreamId);  // Pause not stopped.
440   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
441   counter.ProcessAndGetStats();
442   EXPECT_EQ(1, observer->num_calls_);
443   EXPECT_EQ(6, observer->last_sample_);
444   // Stop pause, add sample and advance 1 intervals.
445   counter.ProcessAndStopPause();
446   counter.Set(12, kStreamId);
447   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
448   counter.ProcessAndGetStats();
449   EXPECT_EQ(2, observer->num_calls_);
450   EXPECT_EQ(0, observer->last_sample_);
451 }
452 
TEST_F(StatsCounterTest,TestAvgCounter_WithoutMinPauseTimePassed)453 TEST_F(StatsCounterTest, TestAvgCounter_WithoutMinPauseTimePassed) {
454   // Samples: | 6 | 2 | - |  // x: empty interval, -: paused
455   // Stats:   | 6 | 2 | - |  // x -> last value reported
456   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
457   AvgCounter counter(&clock_, observer, true);
458   // Add sample and advance 1 intervals.
459   AddSampleAndAdvance(6, kDefaultProcessIntervalMs, &counter);
460   // Process and pause. Verify stats: [6:1].
461   const int64_t kMinMs = 500;
462   counter.ProcessAndPauseForDuration(kMinMs);
463   EXPECT_EQ(1, observer->num_calls_);  // Last value reported.
464   EXPECT_EQ(6, observer->last_sample_);
465   // Min pause time has not pass.
466   clock_.AdvanceTimeMilliseconds(kMinMs - 1);
467   counter.Add(2);  // Pause not stopped.
468   // Make two intervals pass (1 without samples -> ignored while paused).
469   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 2 - (kMinMs - 1));
470   counter.ProcessAndGetStats();
471   EXPECT_EQ(2, observer->num_calls_);
472   EXPECT_EQ(2, observer->last_sample_);
473 }
474 
TEST_F(StatsCounterTest,TestAvgCounter_WithMinPauseTimePassed)475 TEST_F(StatsCounterTest, TestAvgCounter_WithMinPauseTimePassed) {
476   // Samples: | 6 | 2 | x |  // x: empty interval, -: paused
477   // Stats:   | 6 | 2 | 2 |  // x -> last value reported
478   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
479   AvgCounter counter(&clock_, observer, true);
480   // Add sample and advance 1 intervals.
481   AddSampleAndAdvance(6, kDefaultProcessIntervalMs, &counter);
482   // Process and pause. Verify stats: [6:1].
483   const int64_t kMinMs = 500;
484   counter.ProcessAndPauseForDuration(kMinMs);
485   EXPECT_EQ(1, observer->num_calls_);  // Last value reported.
486   EXPECT_EQ(6, observer->last_sample_);
487   // Make min pause time pass.
488   clock_.AdvanceTimeMilliseconds(kMinMs);
489   counter.Add(2);  // Stop pause.
490   // Make two intervals pass (1 without samples -> last value reported).
491   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 2 - kMinMs);
492   counter.ProcessAndGetStats();
493   EXPECT_EQ(3, observer->num_calls_);
494   EXPECT_EQ(2, observer->last_sample_);
495 }
496 
TEST_F(StatsCounterTest,TestRateCounter_IntervalsWithoutSamplesIgnored)497 TEST_F(StatsCounterTest, TestRateCounter_IntervalsWithoutSamplesIgnored) {
498   // Samples: | 50 | x | 20 |  // x: empty interval
499   // Stats:   | 25 | x | 10 |  // x -> ignored
500   const bool kIncludeEmptyIntervals = false;
501   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
502   const int kSample1 = 50;  //  50 / 2 sec
503   const int kSample2 = 20;  //  20 / 2 sec
504   RateCounter counter(&clock_, observer, kIncludeEmptyIntervals);
505   counter.Add(kSample1);
506   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 3 - 1);
507   // Trigger process (sample included in next interval).
508   counter.Add(kSample2);
509   // [25:1], 2 intervals passed (1 without samples -> ignored).
510   EXPECT_EQ(1, observer->num_calls_);
511   EXPECT_EQ(25, observer->last_sample_);
512   // Make next interval pass and verify stats: [10:1],[25:1]
513   clock_.AdvanceTimeMilliseconds(1);
514   counter.ProcessAndGetStats();
515   EXPECT_EQ(2, observer->num_calls_);
516   EXPECT_EQ(10, observer->last_sample_);
517 }
518 
TEST_F(StatsCounterTest,TestRateCounter_IntervalsWithoutSamplesIncluded)519 TEST_F(StatsCounterTest, TestRateCounter_IntervalsWithoutSamplesIncluded) {
520   // Samples: | 50 | x | 20 |  // x: empty interval
521   // Stats:   | 25 | 0 | 10 |  // x -> zero reported
522   const bool kIncludeEmptyIntervals = true;
523   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
524   const int kSample1 = 50;  //  50 / 2 sec
525   const int kSample2 = 20;  //  20 / 2 sec
526   RateCounter counter(&clock_, observer, kIncludeEmptyIntervals);
527   counter.Add(kSample1);
528   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 3 - 1);
529   // Trigger process (sample included in next interval).
530   counter.Add(kSample2);
531   // [0:1],[25:1], 2 intervals passed (1 without samples -> zero reported).
532   EXPECT_EQ(2, observer->num_calls_);
533   EXPECT_EQ(0, observer->last_sample_);
534   // Make last interval pass and verify stats: [0:1],[10:1],[25:1]
535   clock_.AdvanceTimeMilliseconds(1);
536   AggregatedStats stats = counter.ProcessAndGetStats();
537   EXPECT_EQ(25, stats.max);
538   EXPECT_EQ(3, observer->num_calls_);
539   EXPECT_EQ(10, observer->last_sample_);
540 }
541 
TEST_F(StatsCounterTest,TestRateAccCounter_IntervalsWithoutSamplesIncluded)542 TEST_F(StatsCounterTest, TestRateAccCounter_IntervalsWithoutSamplesIncluded) {
543   // Samples: | 12 | x | x | x | 60 |  // x: empty interval
544   // Stats:   | 6  | 0 | 0 | 0 | 24 |  // x -> zero reported
545   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
546   RateAccCounter counter(&clock_, observer, true);
547   VerifyStatsIsNotSet(counter.ProcessAndGetStats());
548   // Advance one interval and verify stats.
549   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
550   VerifyStatsIsNotSet(counter.ProcessAndGetStats());
551   // Add sample and advance 3 intervals (2 w/o samples -> zero reported).
552   counter.Set(12, kStreamId);
553   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 4 - 1);
554   // Trigger process and verify stats: [0:2][6:1]
555   counter.ProcessAndGetStats();
556   EXPECT_EQ(3, observer->num_calls_);
557   EXPECT_EQ(0, observer->last_sample_);
558   // Make next interval pass (1 w/o samples -> zero reported), [0:3][6:1]
559   clock_.AdvanceTimeMilliseconds(1);
560   counter.ProcessAndGetStats();
561   EXPECT_EQ(4, observer->num_calls_);
562   EXPECT_EQ(0, observer->last_sample_);
563   // Insert sample and advance non-complete interval, no change, [0:3][6:1]
564   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
565   counter.Set(60, kStreamId);
566   EXPECT_EQ(4, observer->num_calls_);
567   // Make next interval pass, [0:3][6:1][24:1]
568   clock_.AdvanceTimeMilliseconds(1);
569   AggregatedStats stats = counter.ProcessAndGetStats();
570   EXPECT_EQ(5, observer->num_calls_);
571   EXPECT_EQ(24, observer->last_sample_);
572   EXPECT_EQ(6, stats.average);
573 }
574 
TEST_F(StatsCounterTest,TestRateAccCounter_IntervalsWithoutSamplesIgnored)575 TEST_F(StatsCounterTest, TestRateAccCounter_IntervalsWithoutSamplesIgnored) {
576   // Samples: | 12 | x | x | x | 60 |  // x: empty interval
577   // Stats:   | 6  | x | x | x | 24 |  // x -> ignored
578   StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
579   RateAccCounter counter(&clock_, observer, false);
580   // Add sample and advance 3 intervals (2 w/o samples -> ignored).
581   counter.Set(12, kStreamId);
582   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 4 - 1);
583   // Trigger process and verify stats: [6:1]
584   counter.ProcessAndGetStats();
585   EXPECT_EQ(1, observer->num_calls_);
586   EXPECT_EQ(6, observer->last_sample_);
587   // Make next interval pass (1 w/o samples -> ignored), [6:1]
588   clock_.AdvanceTimeMilliseconds(1);
589   counter.ProcessAndGetStats();
590   EXPECT_EQ(1, observer->num_calls_);
591   // Insert sample and advance non-complete interval, no change, [6:1]
592   clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
593   counter.Set(60, kStreamId);
594   counter.ProcessAndGetStats();
595   EXPECT_EQ(1, observer->num_calls_);
596   // Make next interval pass, [6:1][24:1]
597   clock_.AdvanceTimeMilliseconds(1);
598   counter.ProcessAndGetStats();
599   EXPECT_EQ(2, observer->num_calls_);
600   EXPECT_EQ(24, observer->last_sample_);
601 }
602 
603 }  // namespace webrtc
604