1 /*
2 * Copyright (c) 2014 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 "modules/pacing/bitrate_prober.h"
12
13 #include <algorithm>
14
15 #include "test/explicit_key_value_config.h"
16 #include "test/gtest.h"
17
18 namespace webrtc {
19
TEST(BitrateProberTest,VerifyStatesAndTimeBetweenProbes)20 TEST(BitrateProberTest, VerifyStatesAndTimeBetweenProbes) {
21 const FieldTrialBasedConfig config;
22 BitrateProber prober(config);
23 EXPECT_FALSE(prober.is_probing());
24
25 Timestamp now = Timestamp::Millis(0);
26 const Timestamp start_time = now;
27 EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
28
29 const DataRate kTestBitrate1 = DataRate::KilobitsPerSec(900);
30 const DataRate kTestBitrate2 = DataRate::KilobitsPerSec(1800);
31 const int kClusterSize = 5;
32 const DataSize kProbeSize = DataSize::Bytes(1000);
33 const TimeDelta kMinProbeDuration = TimeDelta::Millis(15);
34
35 prober.CreateProbeCluster(kTestBitrate1, now, 0);
36 prober.CreateProbeCluster(kTestBitrate2, now, 1);
37 EXPECT_FALSE(prober.is_probing());
38
39 prober.OnIncomingPacket(kProbeSize);
40 EXPECT_TRUE(prober.is_probing());
41 EXPECT_EQ(0, prober.CurrentCluster(now)->probe_cluster_id);
42
43 // First packet should probe as soon as possible.
44 EXPECT_EQ(Timestamp::MinusInfinity(), prober.NextProbeTime(now));
45
46 for (int i = 0; i < kClusterSize; ++i) {
47 now = std::max(now, prober.NextProbeTime(now));
48 EXPECT_EQ(now, std::max(now, prober.NextProbeTime(now)));
49 EXPECT_EQ(0, prober.CurrentCluster(now)->probe_cluster_id);
50 prober.ProbeSent(now, kProbeSize);
51 }
52
53 EXPECT_GE(now - start_time, kMinProbeDuration);
54 // Verify that the actual bitrate is withing 10% of the target.
55 DataRate bitrate = kProbeSize * (kClusterSize - 1) / (now - start_time);
56 EXPECT_GT(bitrate, kTestBitrate1 * 0.9);
57 EXPECT_LT(bitrate, kTestBitrate1 * 1.1);
58
59 now = std::max(now, prober.NextProbeTime(now));
60 Timestamp probe2_started = now;
61
62 for (int i = 0; i < kClusterSize; ++i) {
63 now = std::max(now, prober.NextProbeTime(now));
64 EXPECT_EQ(now, std::max(now, prober.NextProbeTime(now)));
65 EXPECT_EQ(1, prober.CurrentCluster(now)->probe_cluster_id);
66 prober.ProbeSent(now, kProbeSize);
67 }
68
69 // Verify that the actual bitrate is withing 10% of the target.
70 TimeDelta duration = now - probe2_started;
71 EXPECT_GE(duration, kMinProbeDuration);
72 bitrate = (kProbeSize * (kClusterSize - 1)) / duration;
73 EXPECT_GT(bitrate, kTestBitrate2 * 0.9);
74 EXPECT_LT(bitrate, kTestBitrate2 * 1.1);
75
76 EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
77 EXPECT_FALSE(prober.is_probing());
78 }
79
TEST(BitrateProberTest,DoesntProbeWithoutRecentPackets)80 TEST(BitrateProberTest, DoesntProbeWithoutRecentPackets) {
81 const FieldTrialBasedConfig config;
82 BitrateProber prober(config);
83 const DataSize kProbeSize = DataSize::Bytes(1000);
84
85 Timestamp now = Timestamp::Zero();
86 EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
87
88 prober.CreateProbeCluster(DataRate::KilobitsPerSec(900), now, 0);
89 EXPECT_FALSE(prober.is_probing());
90
91 prober.OnIncomingPacket(kProbeSize);
92 EXPECT_TRUE(prober.is_probing());
93 EXPECT_EQ(now, std::max(now, prober.NextProbeTime(now)));
94 prober.ProbeSent(now, kProbeSize);
95 }
96
TEST(BitrateProberTest,DoesntDiscardDelayedProbesInLegacyMode)97 TEST(BitrateProberTest, DoesntDiscardDelayedProbesInLegacyMode) {
98 const TimeDelta kMaxProbeDelay = TimeDelta::Millis(3);
99 const test::ExplicitKeyValueConfig trials(
100 "WebRTC-Bwe-ProbingBehavior/"
101 "abort_delayed_probes:0,"
102 "max_probe_delay:3ms/");
103 BitrateProber prober(trials);
104 const DataSize kProbeSize = DataSize::Bytes(1000);
105
106 Timestamp now = Timestamp::Zero();
107 prober.CreateProbeCluster(DataRate::KilobitsPerSec(900), now, 0);
108 prober.OnIncomingPacket(kProbeSize);
109 EXPECT_TRUE(prober.is_probing());
110 EXPECT_EQ(prober.CurrentCluster(now)->probe_cluster_id, 0);
111 // Advance to first probe time and indicate sent probe.
112 now = std::max(now, prober.NextProbeTime(now));
113 prober.ProbeSent(now, kProbeSize);
114
115 // Advance time 1ms past timeout for the next probe.
116 Timestamp next_probe_time = prober.NextProbeTime(now);
117 EXPECT_GT(next_probe_time, now);
118 now += next_probe_time - now + kMaxProbeDelay + TimeDelta::Millis(1);
119
120 EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
121 // Check that legacy behaviour where prober is reset in TimeUntilNextProbe is
122 // no longer there. Probes are no longer retried if they are timed out.
123 prober.OnIncomingPacket(kProbeSize);
124 EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
125 }
126
TEST(BitrateProberTest,DiscardsDelayedProbesWhenNotInLegacyMode)127 TEST(BitrateProberTest, DiscardsDelayedProbesWhenNotInLegacyMode) {
128 const TimeDelta kMaxProbeDelay = TimeDelta::Millis(3);
129 const test::ExplicitKeyValueConfig trials(
130 "WebRTC-Bwe-ProbingBehavior/"
131 "abort_delayed_probes:1,"
132 "max_probe_delay:3ms/");
133 BitrateProber prober(trials);
134 const DataSize kProbeSize = DataSize::Bytes(1000);
135
136 Timestamp now = Timestamp::Zero();
137
138 // Add two probe clusters.
139 prober.CreateProbeCluster(DataRate::KilobitsPerSec(900), now, /*id=*/0);
140
141 prober.OnIncomingPacket(kProbeSize);
142 EXPECT_TRUE(prober.is_probing());
143 EXPECT_EQ(prober.CurrentCluster(now)->probe_cluster_id, 0);
144 // Advance to first probe time and indicate sent probe.
145 now = std::max(now, prober.NextProbeTime(now));
146 prober.ProbeSent(now, kProbeSize);
147
148 // Advance time 1ms past timeout for the next probe.
149 Timestamp next_probe_time = prober.NextProbeTime(now);
150 EXPECT_GT(next_probe_time, now);
151 now += next_probe_time - now + kMaxProbeDelay + TimeDelta::Millis(1);
152
153 // Still indicates the time we wanted to probe at.
154 EXPECT_EQ(prober.NextProbeTime(now), next_probe_time);
155 // First and only cluster removed due to timeout.
156 EXPECT_FALSE(prober.CurrentCluster(now).has_value());
157 }
158
TEST(BitrateProberTest,DoesntInitializeProbingForSmallPackets)159 TEST(BitrateProberTest, DoesntInitializeProbingForSmallPackets) {
160 const FieldTrialBasedConfig config;
161 BitrateProber prober(config);
162
163 prober.SetEnabled(true);
164 EXPECT_FALSE(prober.is_probing());
165
166 prober.OnIncomingPacket(DataSize::Bytes(100));
167 EXPECT_FALSE(prober.is_probing());
168 }
169
TEST(BitrateProberTest,VerifyProbeSizeOnHighBitrate)170 TEST(BitrateProberTest, VerifyProbeSizeOnHighBitrate) {
171 const FieldTrialBasedConfig config;
172 BitrateProber prober(config);
173
174 const DataRate kHighBitrate = DataRate::KilobitsPerSec(10000); // 10 Mbps
175
176 prober.CreateProbeCluster(kHighBitrate, Timestamp::Millis(0),
177 /*cluster_id=*/0);
178 // Probe size should ensure a minimum of 1 ms interval.
179 EXPECT_GT(prober.RecommendedMinProbeSize(),
180 kHighBitrate * TimeDelta::Millis(1));
181 }
182
TEST(BitrateProberTest,MinumumNumberOfProbingPackets)183 TEST(BitrateProberTest, MinumumNumberOfProbingPackets) {
184 const FieldTrialBasedConfig config;
185 BitrateProber prober(config);
186 // Even when probing at a low bitrate we expect a minimum number
187 // of packets to be sent.
188 const DataRate kBitrate = DataRate::KilobitsPerSec(100);
189 const DataSize kPacketSize = DataSize::Bytes(1000);
190
191 Timestamp now = Timestamp::Millis(0);
192 prober.CreateProbeCluster(kBitrate, now, 0);
193 prober.OnIncomingPacket(kPacketSize);
194 for (int i = 0; i < 5; ++i) {
195 EXPECT_TRUE(prober.is_probing());
196 prober.ProbeSent(now, kPacketSize);
197 }
198
199 EXPECT_FALSE(prober.is_probing());
200 }
201
TEST(BitrateProberTest,ScaleBytesUsedForProbing)202 TEST(BitrateProberTest, ScaleBytesUsedForProbing) {
203 const FieldTrialBasedConfig config;
204 BitrateProber prober(config);
205 const DataRate kBitrate = DataRate::KilobitsPerSec(10000); // 10 Mbps.
206 const DataSize kPacketSize = DataSize::Bytes(1000);
207 const DataSize kExpectedDataSent = kBitrate * TimeDelta::Millis(15);
208
209 Timestamp now = Timestamp::Millis(0);
210 prober.CreateProbeCluster(kBitrate, now, /*cluster_id=*/0);
211 prober.OnIncomingPacket(kPacketSize);
212 DataSize data_sent = DataSize::Zero();
213 while (data_sent < kExpectedDataSent) {
214 ASSERT_TRUE(prober.is_probing());
215 prober.ProbeSent(now, kPacketSize);
216 data_sent += kPacketSize;
217 }
218
219 EXPECT_FALSE(prober.is_probing());
220 }
221
TEST(BitrateProberTest,HighBitrateProbing)222 TEST(BitrateProberTest, HighBitrateProbing) {
223 const FieldTrialBasedConfig config;
224 BitrateProber prober(config);
225 const DataRate kBitrate = DataRate::KilobitsPerSec(1000000); // 1 Gbps.
226 const DataSize kPacketSize = DataSize::Bytes(1000);
227 const DataSize kExpectedDataSent = kBitrate * TimeDelta::Millis(15);
228
229 Timestamp now = Timestamp::Millis(0);
230 prober.CreateProbeCluster(kBitrate, now, 0);
231 prober.OnIncomingPacket(kPacketSize);
232 DataSize data_sent = DataSize::Zero();
233 while (data_sent < kExpectedDataSent) {
234 ASSERT_TRUE(prober.is_probing());
235 prober.ProbeSent(now, kPacketSize);
236 data_sent += kPacketSize;
237 }
238
239 EXPECT_FALSE(prober.is_probing());
240 }
241
TEST(BitrateProberTest,ProbeClusterTimeout)242 TEST(BitrateProberTest, ProbeClusterTimeout) {
243 const FieldTrialBasedConfig config;
244 BitrateProber prober(config);
245 const DataRate kBitrate = DataRate::KilobitsPerSec(300);
246 const DataSize kSmallPacketSize = DataSize::Bytes(20);
247 // Expecting two probe clusters of 5 packets each.
248 const DataSize kExpectedDataSent = kSmallPacketSize * 2 * 5;
249 const TimeDelta kTimeout = TimeDelta::Millis(5000);
250
251 Timestamp now = Timestamp::Millis(0);
252 prober.CreateProbeCluster(kBitrate, now, /*cluster_id=*/0);
253 prober.OnIncomingPacket(kSmallPacketSize);
254 EXPECT_FALSE(prober.is_probing());
255 now += kTimeout;
256 prober.CreateProbeCluster(kBitrate / 10, now, /*cluster_id=*/1);
257 prober.OnIncomingPacket(kSmallPacketSize);
258 EXPECT_FALSE(prober.is_probing());
259 now += TimeDelta::Millis(1);
260 prober.CreateProbeCluster(kBitrate / 10, now, /*cluster_id=*/2);
261 prober.OnIncomingPacket(kSmallPacketSize);
262 EXPECT_TRUE(prober.is_probing());
263 DataSize data_sent = DataSize::Zero();
264 while (data_sent < kExpectedDataSent) {
265 ASSERT_TRUE(prober.is_probing());
266 prober.ProbeSent(now, kSmallPacketSize);
267 data_sent += kSmallPacketSize;
268 }
269
270 EXPECT_FALSE(prober.is_probing());
271 }
272 } // namespace webrtc
273