• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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