Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(582)

Side by Side Diff: webrtc/base/rate_limiter_unittest.cc

Issue 2146013002: Reland of actor NACK bitrate allocation (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/base/rate_limiter.cc ('k') | webrtc/base/rate_statistics.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 <algorithm>
12 #include <memory>
13
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 #include "webrtc/base/event.h"
17 #include "webrtc/base/platform_thread.h"
18 #include "webrtc/base/rate_limiter.h"
19 #include "webrtc/base/task_queue.h"
20 #include "webrtc/system_wrappers/include/clock.h"
21
22 namespace webrtc {
23
24 class RateLimitTest : public ::testing::Test {
25 public:
26 RateLimitTest()
27 : clock_(0), rate_limiter(new RateLimiter(&clock_, kWindowSizeMs)) {}
28 virtual ~RateLimitTest() {}
29
30 void SetUp() override { rate_limiter->SetMaxRate(kMaxRateBps); }
31
32 protected:
33 static constexpr int64_t kWindowSizeMs = 1000;
34 static constexpr uint32_t kMaxRateBps = 100000;
35 // Bytes needed to completely saturate the rate limiter.
36 static constexpr size_t kRateFillingBytes =
37 (kMaxRateBps * kWindowSizeMs) / (8 * 1000);
38 SimulatedClock clock_;
39 std::unique_ptr<RateLimiter> rate_limiter;
40 };
41
42 TEST_F(RateLimitTest, IncreasingMaxRate) {
43 // Fill rate, extend window to full size.
44 EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
45 clock_.AdvanceTimeMilliseconds(kWindowSizeMs - 1);
46 EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
47
48 // All rate consumed.
49 EXPECT_FALSE(rate_limiter->TryUseRate(1));
50
51 // Double the available rate and fill that too.
52 rate_limiter->SetMaxRate(kMaxRateBps * 2);
53 EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes));
54
55 // All rate consumed again.
56 EXPECT_FALSE(rate_limiter->TryUseRate(1));
57 }
58
59 TEST_F(RateLimitTest, DecreasingMaxRate) {
60 // Fill rate, extend window to full size.
61 EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
62 clock_.AdvanceTimeMilliseconds(kWindowSizeMs - 1);
63 EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
64
65 // All rate consumed.
66 EXPECT_FALSE(rate_limiter->TryUseRate(1));
67
68 // Halve the available rate and move window so half of the data falls out.
69 rate_limiter->SetMaxRate(kMaxRateBps / 2);
70 clock_.AdvanceTimeMilliseconds(1);
71
72 // All rate still consumed.
73 EXPECT_FALSE(rate_limiter->TryUseRate(1));
74 }
75
76 TEST_F(RateLimitTest, ChangingWindowSize) {
77 // Fill rate, extend window to full size.
78 EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
79 clock_.AdvanceTimeMilliseconds(kWindowSizeMs - 1);
80 EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
81
82 // All rate consumed.
83 EXPECT_FALSE(rate_limiter->TryUseRate(1));
84
85 // Decrease window size so half of the data falls out.
86 rate_limiter->SetWindowSize(kWindowSizeMs / 2);
87 // Average rate should still be the same, so rate is still all consumed.
88 EXPECT_FALSE(rate_limiter->TryUseRate(1));
89
90 // Increase window size again. Now the rate is only half used (removed data
91 // points don't come back to life).
92 rate_limiter->SetWindowSize(kWindowSizeMs);
93 EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
94
95 // All rate consumed again.
96 EXPECT_FALSE(rate_limiter->TryUseRate(1));
97 }
98
99 TEST_F(RateLimitTest, SingleUsageAlwaysOk) {
100 // Using more bytes than can fit in a window is OK for a single packet.
101 EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes + 1));
102 }
103
104 TEST_F(RateLimitTest, WindowSizeLimits) {
105 EXPECT_TRUE(rate_limiter->SetWindowSize(1));
106 EXPECT_FALSE(rate_limiter->SetWindowSize(0));
107 EXPECT_TRUE(rate_limiter->SetWindowSize(kWindowSizeMs));
108 EXPECT_FALSE(rate_limiter->SetWindowSize(kWindowSizeMs + 1));
109 }
110
111 static const int64_t kMaxTimeoutMs = 30000;
112
113 class ThreadTask {
114 public:
115 explicit ThreadTask(RateLimiter* rate_limiter)
116 : rate_limiter_(rate_limiter),
117 start_signal_(false, false),
118 end_signal_(false, false) {}
119 virtual ~ThreadTask() {}
120
121 void Run() {
122 start_signal_.Wait(kMaxTimeoutMs);
123 DoRun();
124 end_signal_.Set();
125 }
126
127 virtual void DoRun() = 0;
128
129 RateLimiter* const rate_limiter_;
130 rtc::Event start_signal_;
131 rtc::Event end_signal_;
132 };
133
134 bool RunTask(void* thread_task) {
135 reinterpret_cast<ThreadTask*>(thread_task)->Run();
136 return false;
137 }
138
139 TEST_F(RateLimitTest, MultiThreadedUsage) {
140 // Simple sanity test, with different threads calling the various methods.
141 // Runs a few simple tasks, each on its own thread, but coordinated with
142 // events so that they run in a serialized order. Intended to catch data
143 // races when run with tsan et al.
144
145 // Half window size, double rate -> same amount of bytes needed to fill rate.
146
147 class SetWindowSizeTask : public ThreadTask {
148 public:
149 explicit SetWindowSizeTask(RateLimiter* rate_limiter)
150 : ThreadTask(rate_limiter) {}
151 virtual ~SetWindowSizeTask() {}
152
153 void DoRun() override {
154 EXPECT_TRUE(rate_limiter_->SetWindowSize(kWindowSizeMs / 2));
155 }
156 } set_window_size_task(rate_limiter.get());
157 rtc::PlatformThread thread1(RunTask, &set_window_size_task, "Thread1");
158 thread1.Start();
159
160 class SetMaxRateTask : public ThreadTask {
161 public:
162 explicit SetMaxRateTask(RateLimiter* rate_limiter)
163 : ThreadTask(rate_limiter) {}
164 virtual ~SetMaxRateTask() {}
165
166 void DoRun() override { rate_limiter_->SetMaxRate(kMaxRateBps * 2); }
167 } set_max_rate_task(rate_limiter.get());
168 rtc::PlatformThread thread2(RunTask, &set_max_rate_task, "Thread2");
169 thread2.Start();
170
171 class UseRateTask : public ThreadTask {
172 public:
173 UseRateTask(RateLimiter* rate_limiter, SimulatedClock* clock)
174 : ThreadTask(rate_limiter), clock_(clock) {}
175 virtual ~UseRateTask() {}
176
177 void DoRun() override {
178 EXPECT_TRUE(rate_limiter_->TryUseRate(kRateFillingBytes / 2));
179 clock_->AdvanceTimeMilliseconds((kWindowSizeMs / 2) - 1);
180 EXPECT_TRUE(rate_limiter_->TryUseRate(kRateFillingBytes / 2));
181 }
182
183 SimulatedClock* const clock_;
184 } use_rate_task(rate_limiter.get(), &clock_);
185 rtc::PlatformThread thread3(RunTask, &use_rate_task, "Thread3");
186 thread3.Start();
187
188 set_window_size_task.start_signal_.Set();
189 EXPECT_TRUE(set_window_size_task.end_signal_.Wait(kMaxTimeoutMs));
190
191 set_max_rate_task.start_signal_.Set();
192 EXPECT_TRUE(set_max_rate_task.end_signal_.Wait(kMaxTimeoutMs));
193
194 use_rate_task.start_signal_.Set();
195 EXPECT_TRUE(use_rate_task.end_signal_.Wait(kMaxTimeoutMs));
196
197 // All rate consumed.
198 EXPECT_FALSE(rate_limiter->TryUseRate(1));
199
200 thread1.Stop();
201 thread2.Stop();
202 thread3.Stop();
203 }
204
205 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/base/rate_limiter.cc ('k') | webrtc/base/rate_statistics.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698