blob: 7484c18a8953106c487087083a14b629330bba31 [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
11#include "webrtc/video/stats_counter.h"
12
asapersson0e9d6d92016-05-23 06:07:55 -070013#include "webrtc/system_wrappers/include/clock.h"
kwibergac9f8762016-09-30 22:29:43 -070014#include "webrtc/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:
35 StatsCounterTest()
36 : clock_(1234) {}
37
38 void AddSampleAndAdvance(int sample, int interval_ms, AvgCounter* counter) {
39 counter->Add(sample);
40 clock_.AdvanceTimeMilliseconds(interval_ms);
41 }
42
43 void SetSampleAndAdvance(int sample,
44 int interval_ms,
45 RateAccCounter* counter) {
asaperssonfe647f42016-11-01 00:21:34 -070046 counter->Set(sample, kStreamId);
asapersson0e9d6d92016-05-23 06:07:55 -070047 clock_.AdvanceTimeMilliseconds(interval_ms);
48 }
49
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
60TEST_F(StatsCounterTest, NoSamples) {
asaperssonce2e1362016-09-09 00:13:35 -070061 AvgCounter counter(&clock_, nullptr, false);
asapersson0e9d6d92016-05-23 06:07:55 -070062 VerifyStatsIsNotSet(counter.GetStats());
63}
64
65TEST_F(StatsCounterTest, TestRegisterObserver) {
66 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
67 const int kSample = 22;
asaperssonce2e1362016-09-09 00:13:35 -070068 AvgCounter counter(&clock_, observer, false);
asaperssone402a142016-10-06 23:39:15 -070069 AddSampleAndAdvance(kSample, kDefaultProcessIntervalMs, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -070070 // Trigger process (sample included in next interval).
71 counter.Add(111);
72 EXPECT_EQ(1, observer->num_calls_);
73}
74
asapersson250fd972016-09-08 00:07:21 -070075TEST_F(StatsCounterTest, HasSample) {
asaperssonce2e1362016-09-09 00:13:35 -070076 AvgCounter counter(&clock_, nullptr, false);
asapersson250fd972016-09-08 00:07:21 -070077 EXPECT_FALSE(counter.HasSample());
78 counter.Add(1);
79 EXPECT_TRUE(counter.HasSample());
80}
81
asapersson0e9d6d92016-05-23 06:07:55 -070082TEST_F(StatsCounterTest, VerifyProcessInterval) {
83 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asaperssonce2e1362016-09-09 00:13:35 -070084 AvgCounter counter(&clock_, observer, false);
asapersson0e9d6d92016-05-23 06:07:55 -070085 counter.Add(4);
asaperssone402a142016-10-06 23:39:15 -070086 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
asapersson0e9d6d92016-05-23 06:07:55 -070087 // 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
102TEST_F(StatsCounterTest, TestMetric_AvgCounter) {
103 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asaperssonce2e1362016-09-09 00:13:35 -0700104 AvgCounter counter(&clock_, observer, false);
asapersson0e9d6d92016-05-23 06:07:55 -0700105 counter.Add(4);
106 counter.Add(8);
107 counter.Add(9);
asaperssone402a142016-10-06 23:39:15 -0700108 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700109 // 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
122TEST_F(StatsCounterTest, TestMetric_MaxCounter) {
asaperssone402a142016-10-06 23:39:15 -0700123 const int64_t kProcessIntervalMs = 1000;
asapersson0e9d6d92016-05-23 06:07:55 -0700124 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asaperssone402a142016-10-06 23:39:15 -0700125 MaxCounter counter(&clock_, observer, kProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700126 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
143TEST_F(StatsCounterTest, TestMetric_PercentCounter) {
144 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
145 PercentCounter counter(&clock_, observer);
146 counter.Add(true);
147 counter.Add(false);
asaperssone402a142016-10-06 23:39:15 -0700148 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700149 // 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
161TEST_F(StatsCounterTest, TestMetric_PermilleCounter) {
162 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
163 PermilleCounter counter(&clock_, observer);
164 counter.Add(true);
165 counter.Add(false);
asaperssone402a142016-10-06 23:39:15 -0700166 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700167 // 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
179TEST_F(StatsCounterTest, TestMetric_RateCounter) {
180 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asapersson5093b382016-08-15 01:20:30 -0700181 RateCounter counter(&clock_, observer, true);
asapersson0e9d6d92016-05-23 06:07:55 -0700182 counter.Add(186);
183 counter.Add(350);
184 counter.Add(22);
asaperssone402a142016-10-06 23:39:15 -0700185 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700186 // 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
198TEST_F(StatsCounterTest, TestMetric_RateAccCounter) {
199 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asapersson5093b382016-08-15 01:20:30 -0700200 RateAccCounter counter(&clock_, observer, true);
asaperssonfe647f42016-11-01 00:21:34 -0700201 counter.Set(175, kStreamId);
202 counter.Set(188, kStreamId);
asaperssone402a142016-10-06 23:39:15 -0700203 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700204 // Trigger process (sample included in next interval).
asaperssonfe647f42016-11-01 00:21:34 -0700205 counter.Set(192, kStreamId);
asapersson0e9d6d92016-05-23 06:07:55 -0700206 // 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
asaperssonfe647f42016-11-01 00:21:34 -0700216TEST_F(StatsCounterTest, TestMetric_RateAccCounterWithMultipleStreamIds) {
217 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
218 RateAccCounter counter(&clock_, observer, true);
219 counter.Set(175, kStreamId);
220 counter.Set(188, kStreamId);
221 counter.Set(100, kStreamId + 1);
222 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
223 // Trigger process (sample included in next interval).
224 counter.Set(150, kStreamId + 1);
225 // Rate per interval: ((188 - 0) + (100 - 0)) / 2 sec = 144 samples/sec
226 EXPECT_EQ(1, observer->num_calls_);
227 EXPECT_EQ(144, observer->last_sample_);
228 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
229 // Trigger process (sample included in next interval).
230 counter.Set(198, kStreamId);
231 // Rate per interval: (0 + (150 - 100)) / 2 sec = 25 samples/sec
232 EXPECT_EQ(2, observer->num_calls_);
233 EXPECT_EQ(25, observer->last_sample_);
234 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
235 // Trigger process (sample included in next interval).
236 counter.Set(200, kStreamId);
237 // Rate per interval: ((198 - 188) + (0)) / 2 sec = 5 samples/sec
238 EXPECT_EQ(3, observer->num_calls_);
239 EXPECT_EQ(5, observer->last_sample_);
240 // Aggregated stats.
241 AggregatedStats stats = counter.GetStats();
242 EXPECT_EQ(3, stats.num_samples);
243 EXPECT_EQ(5, stats.min);
244 EXPECT_EQ(144, stats.max);
245}
246
asapersson0e9d6d92016-05-23 06:07:55 -0700247TEST_F(StatsCounterTest, TestGetStats_MultipleIntervals) {
asaperssonce2e1362016-09-09 00:13:35 -0700248 AvgCounter counter(&clock_, nullptr, false);
asapersson0e9d6d92016-05-23 06:07:55 -0700249 const int kSample1 = 1;
250 const int kSample2 = 5;
251 const int kSample3 = 8;
252 const int kSample4 = 11;
253 const int kSample5 = 50;
asaperssone402a142016-10-06 23:39:15 -0700254 AddSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
255 AddSampleAndAdvance(kSample2, kDefaultProcessIntervalMs, &counter);
256 AddSampleAndAdvance(kSample3, kDefaultProcessIntervalMs, &counter);
257 AddSampleAndAdvance(kSample4, kDefaultProcessIntervalMs, &counter);
258 AddSampleAndAdvance(kSample5, kDefaultProcessIntervalMs, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -0700259 // Trigger process (sample included in next interval).
260 counter.Add(111);
261 AggregatedStats stats = counter.GetStats();
262 EXPECT_EQ(5, stats.num_samples);
263 EXPECT_EQ(kSample1, stats.min);
264 EXPECT_EQ(kSample5, stats.max);
265 EXPECT_EQ(15, stats.average);
266}
267
268TEST_F(StatsCounterTest, TestGetStatsTwice) {
269 const int kSample1 = 4;
270 const int kSample2 = 7;
asaperssonce2e1362016-09-09 00:13:35 -0700271 AvgCounter counter(&clock_, nullptr, false);
asaperssone402a142016-10-06 23:39:15 -0700272 AddSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -0700273 // Trigger process (sample included in next interval).
274 counter.Add(kSample2);
275 AggregatedStats stats = counter.GetStats();
276 EXPECT_EQ(1, stats.num_samples);
277 EXPECT_EQ(kSample1, stats.min);
278 EXPECT_EQ(kSample1, stats.max);
279 // Trigger process (sample included in next interval).
asaperssone402a142016-10-06 23:39:15 -0700280 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asapersson0e9d6d92016-05-23 06:07:55 -0700281 counter.Add(111);
282 stats = counter.GetStats();
283 EXPECT_EQ(2, stats.num_samples);
284 EXPECT_EQ(kSample1, stats.min);
285 EXPECT_EQ(kSample2, stats.max);
286 EXPECT_EQ(6, stats.average);
287}
288
289TEST_F(StatsCounterTest, TestRateAccCounter_NegativeRateIgnored) {
290 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
291 const int kSample1 = 200; // 200 / 2 sec
292 const int kSample2 = 100; // -100 / 2 sec - negative ignored
293 const int kSample3 = 700; // 600 / 2 sec
asapersson5093b382016-08-15 01:20:30 -0700294 RateAccCounter counter(&clock_, observer, true);
asaperssone402a142016-10-06 23:39:15 -0700295 SetSampleAndAdvance(kSample1, kDefaultProcessIntervalMs, &counter);
296 SetSampleAndAdvance(kSample2, kDefaultProcessIntervalMs, &counter);
297 SetSampleAndAdvance(kSample3, kDefaultProcessIntervalMs, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -0700298 EXPECT_EQ(1, observer->num_calls_);
299 EXPECT_EQ(100, observer->last_sample_);
300 // Trigger process (sample included in next interval).
asaperssonfe647f42016-11-01 00:21:34 -0700301 counter.Set(2000, kStreamId);
asapersson0e9d6d92016-05-23 06:07:55 -0700302 EXPECT_EQ(2, observer->num_calls_);
303 EXPECT_EQ(300, observer->last_sample_);
304 // Aggregated stats.
305 AggregatedStats stats = counter.GetStats();
306 EXPECT_EQ(2, stats.num_samples);
307 EXPECT_EQ(100, stats.min);
308 EXPECT_EQ(300, stats.max);
309 EXPECT_EQ(200, stats.average);
310}
311
asaperssonce2e1362016-09-09 00:13:35 -0700312TEST_F(StatsCounterTest, TestAvgCounter_IntervalsWithoutSamplesIncluded) {
313 // Samples: | 6 | x | x | 8 | // x: empty interval
314 // Stats: | 6 | 6 | 6 | 8 | // x -> last value reported
asapersson0e9d6d92016-05-23 06:07:55 -0700315 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
asaperssonce2e1362016-09-09 00:13:35 -0700316 AvgCounter counter(&clock_, observer, true);
asaperssone402a142016-10-06 23:39:15 -0700317 AddSampleAndAdvance(6, kDefaultProcessIntervalMs * 4 - 1, &counter);
asapersson0e9d6d92016-05-23 06:07:55 -0700318 // Trigger process (sample included in next interval).
319 counter.Add(8);
asaperssonce2e1362016-09-09 00:13:35 -0700320 // [6:3], 3 intervals passed (2 without samples -> last value reported).
321 AggregatedStats stats = counter.ProcessAndGetStats();
322 EXPECT_EQ(3, stats.num_samples);
asapersson0e9d6d92016-05-23 06:07:55 -0700323 EXPECT_EQ(6, stats.min);
asaperssonce2e1362016-09-09 00:13:35 -0700324 EXPECT_EQ(6, stats.max);
325 // Make next interval pass and verify stats: [6:3],[8:1]
326 clock_.AdvanceTimeMilliseconds(1);
327 counter.ProcessAndGetStats();
328 EXPECT_EQ(4, observer->num_calls_);
329 EXPECT_EQ(8, observer->last_sample_);
330}
331
332TEST_F(StatsCounterTest, TestAvgCounter_WithPause) {
333 // Samples: | 6 | x | x | x | - | 22 | x | // x: empty interval, -: paused
334 // Stats: | 6 | 6 | 6 | 6 | - | 22 | 22 | // x -> last value reported
335 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
336 AvgCounter counter(&clock_, observer, true);
337 // Add sample and advance 3 intervals (2 w/o samples -> last value reported).
asaperssone402a142016-10-06 23:39:15 -0700338 AddSampleAndAdvance(6, kDefaultProcessIntervalMs * 4 - 1, &counter);
asaperssonce2e1362016-09-09 00:13:35 -0700339 // Trigger process and verify stats: [6:3]
340 counter.ProcessAndGetStats();
341 EXPECT_EQ(3, observer->num_calls_);
342 EXPECT_EQ(6, observer->last_sample_);
343 // Make next interval pass (1 without samples).
344 // Process and pause. Verify stats: [6:4].
345 clock_.AdvanceTimeMilliseconds(1);
346 counter.ProcessAndPause();
347 EXPECT_EQ(4, observer->num_calls_); // Last value reported.
348 EXPECT_EQ(6, observer->last_sample_);
349 // Make next interval pass (1 without samples -> ignored while paused).
asaperssone402a142016-10-06 23:39:15 -0700350 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 2 - 1);
asaperssonce2e1362016-09-09 00:13:35 -0700351 counter.Add(22); // Stops pause.
352 EXPECT_EQ(4, observer->num_calls_);
353 EXPECT_EQ(6, observer->last_sample_);
354 // Make next interval pass, [6:4][22:1]
355 clock_.AdvanceTimeMilliseconds(1);
356 counter.ProcessAndGetStats();
357 EXPECT_EQ(5, observer->num_calls_);
358 EXPECT_EQ(22, observer->last_sample_);
359 // Make 1 interval pass (1 w/o samples -> pause stopped, last value reported).
asaperssone402a142016-10-06 23:39:15 -0700360 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asaperssonce2e1362016-09-09 00:13:35 -0700361 counter.ProcessAndGetStats();
362 EXPECT_EQ(6, observer->num_calls_);
363 EXPECT_EQ(22, observer->last_sample_);
asapersson0e9d6d92016-05-23 06:07:55 -0700364}
365
asapersson5093b382016-08-15 01:20:30 -0700366TEST_F(StatsCounterTest, TestRateCounter_IntervalsWithoutSamplesIgnored) {
asaperssonce2e1362016-09-09 00:13:35 -0700367 // Samples: | 50 | x | 20 | // x: empty interval
368 // Stats: | 25 | x | 10 | // x -> ignored
asapersson5093b382016-08-15 01:20:30 -0700369 const bool kIncludeEmptyIntervals = false;
asapersson0e9d6d92016-05-23 06:07:55 -0700370 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
371 const int kSample1 = 50; // 50 / 2 sec
372 const int kSample2 = 20; // 20 / 2 sec
asapersson5093b382016-08-15 01:20:30 -0700373 RateCounter counter(&clock_, observer, kIncludeEmptyIntervals);
374 counter.Add(kSample1);
asaperssone402a142016-10-06 23:39:15 -0700375 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 3 - 1);
asapersson5093b382016-08-15 01:20:30 -0700376 // Trigger process (sample included in next interval).
377 counter.Add(kSample2);
asaperssonce2e1362016-09-09 00:13:35 -0700378 // [25:1], 2 intervals passed (1 without samples -> ignored).
asapersson5093b382016-08-15 01:20:30 -0700379 EXPECT_EQ(1, observer->num_calls_);
380 EXPECT_EQ(25, observer->last_sample_);
asaperssonce2e1362016-09-09 00:13:35 -0700381 // Make next interval pass and verify stats: [10:1],[25:1]
asapersson5093b382016-08-15 01:20:30 -0700382 clock_.AdvanceTimeMilliseconds(1);
asaperssonce2e1362016-09-09 00:13:35 -0700383 counter.ProcessAndGetStats();
asapersson5093b382016-08-15 01:20:30 -0700384 EXPECT_EQ(2, observer->num_calls_);
385 EXPECT_EQ(10, observer->last_sample_);
asapersson5093b382016-08-15 01:20:30 -0700386}
387
388TEST_F(StatsCounterTest, TestRateCounter_IntervalsWithoutSamplesIncluded) {
asaperssonce2e1362016-09-09 00:13:35 -0700389 // Samples: | 50 | x | 20 | // x: empty interval
390 // Stats: | 25 | 0 | 10 | // x -> zero reported
asapersson5093b382016-08-15 01:20:30 -0700391 const bool kIncludeEmptyIntervals = true;
392 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
393 const int kSample1 = 50; // 50 / 2 sec
394 const int kSample2 = 20; // 20 / 2 sec
395 RateCounter counter(&clock_, observer, kIncludeEmptyIntervals);
asapersson0e9d6d92016-05-23 06:07:55 -0700396 counter.Add(kSample1);
asaperssone402a142016-10-06 23:39:15 -0700397 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 3 - 1);
asapersson0e9d6d92016-05-23 06:07:55 -0700398 // Trigger process (sample included in next interval).
399 counter.Add(kSample2);
asaperssonce2e1362016-09-09 00:13:35 -0700400 // [0:1],[25:1], 2 intervals passed (1 without samples -> zero reported).
asapersson0e9d6d92016-05-23 06:07:55 -0700401 EXPECT_EQ(2, observer->num_calls_);
asaperssonce2e1362016-09-09 00:13:35 -0700402 EXPECT_EQ(0, observer->last_sample_);
403 // Make last interval pass and verify stats: [0:1],[10:1],[25:1]
asapersson0e9d6d92016-05-23 06:07:55 -0700404 clock_.AdvanceTimeMilliseconds(1);
asaperssonce2e1362016-09-09 00:13:35 -0700405 AggregatedStats stats = counter.ProcessAndGetStats();
406 EXPECT_EQ(25, stats.max);
asapersson0e9d6d92016-05-23 06:07:55 -0700407 EXPECT_EQ(3, observer->num_calls_);
408 EXPECT_EQ(10, observer->last_sample_);
asaperssonce2e1362016-09-09 00:13:35 -0700409}
410
411TEST_F(StatsCounterTest, TestRateAccCounter_IntervalsWithoutSamplesIncluded) {
412 // Samples: | 12 | x | x | x | 60 | // x: empty interval
413 // Stats: | 6 | 0 | 0 | 0 | 24 | // x -> zero reported
414 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
415 RateAccCounter counter(&clock_, observer, true);
416 VerifyStatsIsNotSet(counter.ProcessAndGetStats());
417 // Advance one interval and verify stats.
asaperssone402a142016-10-06 23:39:15 -0700418 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs);
asaperssonce2e1362016-09-09 00:13:35 -0700419 VerifyStatsIsNotSet(counter.ProcessAndGetStats());
420 // Add sample and advance 3 intervals (2 w/o samples -> zero reported).
asaperssonfe647f42016-11-01 00:21:34 -0700421 counter.Set(12, kStreamId);
asaperssone402a142016-10-06 23:39:15 -0700422 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 4 - 1);
asaperssonce2e1362016-09-09 00:13:35 -0700423 // Trigger process and verify stats: [0:2][6:1]
424 counter.ProcessAndGetStats();
425 EXPECT_EQ(3, observer->num_calls_);
426 EXPECT_EQ(0, observer->last_sample_);
427 // Make next interval pass (1 w/o samples -> zero reported), [0:3][6:1]
428 clock_.AdvanceTimeMilliseconds(1);
429 counter.ProcessAndGetStats();
430 EXPECT_EQ(4, observer->num_calls_);
431 EXPECT_EQ(0, observer->last_sample_);
432 // Insert sample and advance non-complete interval, no change, [0:3][6:1]
asaperssone402a142016-10-06 23:39:15 -0700433 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
asaperssonfe647f42016-11-01 00:21:34 -0700434 counter.Set(60, kStreamId);
asaperssonce2e1362016-09-09 00:13:35 -0700435 EXPECT_EQ(4, observer->num_calls_);
436 // Make next interval pass, [0:3][6:1][24:1]
437 clock_.AdvanceTimeMilliseconds(1);
438 AggregatedStats stats = counter.ProcessAndGetStats();
439 EXPECT_EQ(5, observer->num_calls_);
440 EXPECT_EQ(24, observer->last_sample_);
441 EXPECT_EQ(6, stats.average);
442}
443
444TEST_F(StatsCounterTest, TestRateAccCounter_IntervalsWithoutSamplesIgnored) {
445 // Samples: | 12 | x | x | x | 60 | // x: empty interval
446 // Stats: | 6 | x | x | x | 24 | // x -> ignored
447 StatsCounterObserverImpl* observer = new StatsCounterObserverImpl();
448 RateAccCounter counter(&clock_, observer, false);
449 // Add sample and advance 3 intervals (2 w/o samples -> ignored).
asaperssonfe647f42016-11-01 00:21:34 -0700450 counter.Set(12, kStreamId);
asaperssone402a142016-10-06 23:39:15 -0700451 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs * 4 - 1);
asaperssonce2e1362016-09-09 00:13:35 -0700452 // Trigger process and verify stats: [6:1]
453 counter.ProcessAndGetStats();
454 EXPECT_EQ(1, observer->num_calls_);
455 EXPECT_EQ(6, observer->last_sample_);
456 // Make next interval pass (1 w/o samples -> ignored), [6:1]
457 clock_.AdvanceTimeMilliseconds(1);
458 counter.ProcessAndGetStats();
459 EXPECT_EQ(1, observer->num_calls_);
460 // Insert sample and advance non-complete interval, no change, [6:1]
asaperssone402a142016-10-06 23:39:15 -0700461 clock_.AdvanceTimeMilliseconds(kDefaultProcessIntervalMs - 1);
asaperssonfe647f42016-11-01 00:21:34 -0700462 counter.Set(60, kStreamId);
asaperssonce2e1362016-09-09 00:13:35 -0700463 counter.ProcessAndGetStats();
464 EXPECT_EQ(1, observer->num_calls_);
465 // Make next interval pass, [6:1][24:1]
466 clock_.AdvanceTimeMilliseconds(1);
467 counter.ProcessAndGetStats();
468 EXPECT_EQ(2, observer->num_calls_);
469 EXPECT_EQ(24, observer->last_sample_);
asapersson0e9d6d92016-05-23 06:07:55 -0700470}
471
472} // namespace webrtc