1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2015 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rate_tracker.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker namespace rtc {
16*d9f75844SAndroid Build Coastguard Worker namespace {
17*d9f75844SAndroid Build Coastguard Worker const uint32_t kBucketIntervalMs = 100;
18*d9f75844SAndroid Build Coastguard Worker } // namespace
19*d9f75844SAndroid Build Coastguard Worker
20*d9f75844SAndroid Build Coastguard Worker class RateTrackerForTest : public RateTracker {
21*d9f75844SAndroid Build Coastguard Worker public:
RateTrackerForTest()22*d9f75844SAndroid Build Coastguard Worker RateTrackerForTest() : RateTracker(kBucketIntervalMs, 10u), time_(0) {}
Time() const23*d9f75844SAndroid Build Coastguard Worker int64_t Time() const override { return time_; }
AdvanceTime(int delta)24*d9f75844SAndroid Build Coastguard Worker void AdvanceTime(int delta) { time_ += delta; }
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker private:
27*d9f75844SAndroid Build Coastguard Worker int64_t time_;
28*d9f75844SAndroid Build Coastguard Worker };
29*d9f75844SAndroid Build Coastguard Worker
TEST(RateTrackerTest,Test30FPS)30*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, Test30FPS) {
31*d9f75844SAndroid Build Coastguard Worker RateTrackerForTest tracker;
32*d9f75844SAndroid Build Coastguard Worker
33*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 300; ++i) {
34*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1);
35*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(33);
36*d9f75844SAndroid Build Coastguard Worker if (i % 3 == 0) {
37*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(1);
38*d9f75844SAndroid Build Coastguard Worker }
39*d9f75844SAndroid Build Coastguard Worker }
40*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(30.0, tracker.ComputeRateForInterval(50000));
41*d9f75844SAndroid Build Coastguard Worker }
42*d9f75844SAndroid Build Coastguard Worker
TEST(RateTrackerTest,Test60FPS)43*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, Test60FPS) {
44*d9f75844SAndroid Build Coastguard Worker RateTrackerForTest tracker;
45*d9f75844SAndroid Build Coastguard Worker
46*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 300; ++i) {
47*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1);
48*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(16);
49*d9f75844SAndroid Build Coastguard Worker if (i % 3 != 0) {
50*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(1);
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker }
53*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(60.0, tracker.ComputeRateForInterval(1000));
54*d9f75844SAndroid Build Coastguard Worker }
55*d9f75844SAndroid Build Coastguard Worker
TEST(RateTrackerTest,TestRateTrackerBasics)56*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestRateTrackerBasics) {
57*d9f75844SAndroid Build Coastguard Worker RateTrackerForTest tracker;
58*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRateForInterval(1000));
59*d9f75844SAndroid Build Coastguard Worker
60*d9f75844SAndroid Build Coastguard Worker // Add a sample.
61*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1234);
62*d9f75844SAndroid Build Coastguard Worker // Advance the clock by less than one bucket interval (no rate returned).
63*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(kBucketIntervalMs - 1);
64*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRate());
65*d9f75844SAndroid Build Coastguard Worker // Advance the clock by 100 ms (one bucket interval).
66*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(1);
67*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeRateForInterval(1000));
68*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeRate());
69*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1234U, tracker.TotalSampleCount());
70*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeTotalRate());
71*d9f75844SAndroid Build Coastguard Worker
72*d9f75844SAndroid Build Coastguard Worker // Repeat.
73*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1234);
74*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(100);
75*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeRateForInterval(1000));
76*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeRate());
77*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1234U * 2, tracker.TotalSampleCount());
78*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeTotalRate());
79*d9f75844SAndroid Build Coastguard Worker
80*d9f75844SAndroid Build Coastguard Worker // Advance the clock by 800 ms, so we've elapsed a full second.
81*d9f75844SAndroid Build Coastguard Worker // units_second should now be filled in properly.
82*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(800);
83*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeRateForInterval(1000));
84*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeRate());
85*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1234U * 2, tracker.TotalSampleCount());
86*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeTotalRate());
87*d9f75844SAndroid Build Coastguard Worker
88*d9f75844SAndroid Build Coastguard Worker // Poll the tracker again immediately. The reported rate should stay the same.
89*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeRateForInterval(1000));
90*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeRate());
91*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1234U * 2, tracker.TotalSampleCount());
92*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeTotalRate());
93*d9f75844SAndroid Build Coastguard Worker
94*d9f75844SAndroid Build Coastguard Worker // Do nothing and advance by a second. We should drop down to zero.
95*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(1000);
96*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRateForInterval(1000));
97*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRate());
98*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1234U * 2, tracker.TotalSampleCount());
99*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1234.0, tracker.ComputeTotalRate());
100*d9f75844SAndroid Build Coastguard Worker
101*d9f75844SAndroid Build Coastguard Worker // Send a bunch of data at a constant rate for 5.5 "seconds".
102*d9f75844SAndroid Build Coastguard Worker // We should report the rate properly.
103*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 5500; i += 100) {
104*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(9876U);
105*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(100);
106*d9f75844SAndroid Build Coastguard Worker }
107*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(9876.0 * 10.0, tracker.ComputeRateForInterval(1000));
108*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(9876.0 * 10.0, tracker.ComputeRate());
109*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1234U * 2 + 9876U * 55, tracker.TotalSampleCount());
110*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ((1234.0 * 2.0 + 9876.0 * 55.0) / 7.5,
111*d9f75844SAndroid Build Coastguard Worker tracker.ComputeTotalRate());
112*d9f75844SAndroid Build Coastguard Worker
113*d9f75844SAndroid Build Coastguard Worker // Advance the clock by 500 ms. Since we sent nothing over this half-second,
114*d9f75844SAndroid Build Coastguard Worker // the reported rate should be reduced by half.
115*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(500);
116*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(9876.0 * 5.0, tracker.ComputeRateForInterval(1000));
117*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(9876.0 * 5.0, tracker.ComputeRate());
118*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1234U * 2 + 9876U * 55, tracker.TotalSampleCount());
119*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ((1234.0 * 2.0 + 9876.0 * 55.0) / 8.0,
120*d9f75844SAndroid Build Coastguard Worker tracker.ComputeTotalRate());
121*d9f75844SAndroid Build Coastguard Worker
122*d9f75844SAndroid Build Coastguard Worker // Rate over the last half second should be zero.
123*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRateForInterval(500));
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker
TEST(RateTrackerTest,TestLongPeriodBetweenSamples)126*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestLongPeriodBetweenSamples) {
127*d9f75844SAndroid Build Coastguard Worker RateTrackerForTest tracker;
128*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1);
129*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(1000);
130*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1.0, tracker.ComputeRate());
131*d9f75844SAndroid Build Coastguard Worker
132*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(2000);
133*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRate());
134*d9f75844SAndroid Build Coastguard Worker
135*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(2000);
136*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1);
137*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1.0, tracker.ComputeRate());
138*d9f75844SAndroid Build Coastguard Worker }
139*d9f75844SAndroid Build Coastguard Worker
TEST(RateTrackerTest,TestRolloff)140*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestRolloff) {
141*d9f75844SAndroid Build Coastguard Worker RateTrackerForTest tracker;
142*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) {
143*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1U);
144*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(100);
145*d9f75844SAndroid Build Coastguard Worker }
146*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(10.0, tracker.ComputeRate());
147*d9f75844SAndroid Build Coastguard Worker
148*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) {
149*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1U);
150*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(50);
151*d9f75844SAndroid Build Coastguard Worker }
152*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(15.0, tracker.ComputeRate());
153*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(20.0, tracker.ComputeRateForInterval(500));
154*d9f75844SAndroid Build Coastguard Worker
155*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) {
156*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1U);
157*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(50);
158*d9f75844SAndroid Build Coastguard Worker }
159*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(20.0, tracker.ComputeRate());
160*d9f75844SAndroid Build Coastguard Worker }
161*d9f75844SAndroid Build Coastguard Worker
TEST(RateTrackerTest,TestGetUnitSecondsAfterInitialValue)162*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestGetUnitSecondsAfterInitialValue) {
163*d9f75844SAndroid Build Coastguard Worker RateTrackerForTest tracker;
164*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(1234);
165*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(1000);
166*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(1234.0, tracker.ComputeRateForInterval(1000));
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker
TEST(RateTrackerTest,TestLargeNumbers)169*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestLargeNumbers) {
170*d9f75844SAndroid Build Coastguard Worker RateTrackerForTest tracker;
171*d9f75844SAndroid Build Coastguard Worker const uint64_t large_number = 0x100000000;
172*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(large_number);
173*d9f75844SAndroid Build Coastguard Worker tracker.AdvanceTime(1000);
174*d9f75844SAndroid Build Coastguard Worker tracker.AddSamples(large_number);
175*d9f75844SAndroid Build Coastguard Worker EXPECT_DOUBLE_EQ(large_number * 2, tracker.ComputeRate());
176*d9f75844SAndroid Build Coastguard Worker }
177*d9f75844SAndroid Build Coastguard Worker
178*d9f75844SAndroid Build Coastguard Worker } // namespace rtc
179