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