xref: /aosp_15_r20/external/webrtc/modules/pacing/bitrate_prober_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2014 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 "modules/pacing/bitrate_prober.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include "api/units/data_rate.h"
16*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
17*d9f75844SAndroid Build Coastguard Worker #include "api/units/timestamp.h"
18*d9f75844SAndroid Build Coastguard Worker #include "test/explicit_key_value_config.h"
19*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
20*d9f75844SAndroid Build Coastguard Worker 
21*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
22*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,VerifyStatesAndTimeBetweenProbes)23*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, VerifyStatesAndTimeBetweenProbes) {
24*d9f75844SAndroid Build Coastguard Worker   const FieldTrialBasedConfig config;
25*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
26*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker   Timestamp now = Timestamp::Zero();
29*d9f75844SAndroid Build Coastguard Worker   const Timestamp start_time = now;
30*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
31*d9f75844SAndroid Build Coastguard Worker 
32*d9f75844SAndroid Build Coastguard Worker   const DataRate kTestBitrate1 = DataRate::KilobitsPerSec(900);
33*d9f75844SAndroid Build Coastguard Worker   const DataRate kTestBitrate2 = DataRate::KilobitsPerSec(1800);
34*d9f75844SAndroid Build Coastguard Worker   const int kClusterSize = 5;
35*d9f75844SAndroid Build Coastguard Worker   const DataSize kProbeSize = DataSize::Bytes(1000);
36*d9f75844SAndroid Build Coastguard Worker   const TimeDelta kMinProbeDuration = TimeDelta::Millis(15);
37*d9f75844SAndroid Build Coastguard Worker 
38*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = now,
39*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kTestBitrate1,
40*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
41*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
42*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
43*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = now,
44*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kTestBitrate2,
45*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
46*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
47*d9f75844SAndroid Build Coastguard Worker                              .id = 1});
48*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
49*d9f75844SAndroid Build Coastguard Worker 
50*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kProbeSize);
51*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(prober.is_probing());
52*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0, prober.CurrentCluster(now)->probe_cluster_id);
53*d9f75844SAndroid Build Coastguard Worker 
54*d9f75844SAndroid Build Coastguard Worker   // First packet should probe as soon as possible.
55*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(Timestamp::MinusInfinity(), prober.NextProbeTime(now));
56*d9f75844SAndroid Build Coastguard Worker 
57*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < kClusterSize; ++i) {
58*d9f75844SAndroid Build Coastguard Worker     now = std::max(now, prober.NextProbeTime(now));
59*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(now, std::max(now, prober.NextProbeTime(now)));
60*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(0, prober.CurrentCluster(now)->probe_cluster_id);
61*d9f75844SAndroid Build Coastguard Worker     prober.ProbeSent(now, kProbeSize);
62*d9f75844SAndroid Build Coastguard Worker   }
63*d9f75844SAndroid Build Coastguard Worker 
64*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(now - start_time, kMinProbeDuration);
65*d9f75844SAndroid Build Coastguard Worker   // Verify that the actual bitrate is withing 10% of the target.
66*d9f75844SAndroid Build Coastguard Worker   DataRate bitrate = kProbeSize * (kClusterSize - 1) / (now - start_time);
67*d9f75844SAndroid Build Coastguard Worker   EXPECT_GT(bitrate, kTestBitrate1 * 0.9);
68*d9f75844SAndroid Build Coastguard Worker   EXPECT_LT(bitrate, kTestBitrate1 * 1.1);
69*d9f75844SAndroid Build Coastguard Worker 
70*d9f75844SAndroid Build Coastguard Worker   now = std::max(now, prober.NextProbeTime(now));
71*d9f75844SAndroid Build Coastguard Worker   Timestamp probe2_started = now;
72*d9f75844SAndroid Build Coastguard Worker 
73*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < kClusterSize; ++i) {
74*d9f75844SAndroid Build Coastguard Worker     now = std::max(now, prober.NextProbeTime(now));
75*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(now, std::max(now, prober.NextProbeTime(now)));
76*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1, prober.CurrentCluster(now)->probe_cluster_id);
77*d9f75844SAndroid Build Coastguard Worker     prober.ProbeSent(now, kProbeSize);
78*d9f75844SAndroid Build Coastguard Worker   }
79*d9f75844SAndroid Build Coastguard Worker 
80*d9f75844SAndroid Build Coastguard Worker   // Verify that the actual bitrate is withing 10% of the target.
81*d9f75844SAndroid Build Coastguard Worker   TimeDelta duration = now - probe2_started;
82*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(duration, kMinProbeDuration);
83*d9f75844SAndroid Build Coastguard Worker   bitrate = (kProbeSize * (kClusterSize - 1)) / duration;
84*d9f75844SAndroid Build Coastguard Worker   EXPECT_GT(bitrate, kTestBitrate2 * 0.9);
85*d9f75844SAndroid Build Coastguard Worker   EXPECT_LT(bitrate, kTestBitrate2 * 1.1);
86*d9f75844SAndroid Build Coastguard Worker 
87*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
88*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
89*d9f75844SAndroid Build Coastguard Worker }
90*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,DoesntProbeWithoutRecentPackets)91*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, DoesntProbeWithoutRecentPackets) {
92*d9f75844SAndroid Build Coastguard Worker   const FieldTrialBasedConfig config;
93*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
94*d9f75844SAndroid Build Coastguard Worker   const DataSize kProbeSize = DataSize::Bytes(1000);
95*d9f75844SAndroid Build Coastguard Worker 
96*d9f75844SAndroid Build Coastguard Worker   Timestamp now = Timestamp::Zero();
97*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
98*d9f75844SAndroid Build Coastguard Worker 
99*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = now,
100*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = DataRate::KilobitsPerSec(900),
101*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
102*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
103*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
104*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
105*d9f75844SAndroid Build Coastguard Worker 
106*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kProbeSize);
107*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(prober.is_probing());
108*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(now, std::max(now, prober.NextProbeTime(now)));
109*d9f75844SAndroid Build Coastguard Worker   prober.ProbeSent(now, kProbeSize);
110*d9f75844SAndroid Build Coastguard Worker }
111*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,DiscardsDelayedProbes)112*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, DiscardsDelayedProbes) {
113*d9f75844SAndroid Build Coastguard Worker   const TimeDelta kMaxProbeDelay = TimeDelta::Millis(3);
114*d9f75844SAndroid Build Coastguard Worker   const test::ExplicitKeyValueConfig trials(
115*d9f75844SAndroid Build Coastguard Worker       "WebRTC-Bwe-ProbingBehavior/"
116*d9f75844SAndroid Build Coastguard Worker       "abort_delayed_probes:1,"
117*d9f75844SAndroid Build Coastguard Worker       "max_probe_delay:3ms/");
118*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(trials);
119*d9f75844SAndroid Build Coastguard Worker   const DataSize kProbeSize = DataSize::Bytes(1000);
120*d9f75844SAndroid Build Coastguard Worker 
121*d9f75844SAndroid Build Coastguard Worker   Timestamp now = Timestamp::Zero();
122*d9f75844SAndroid Build Coastguard Worker 
123*d9f75844SAndroid Build Coastguard Worker   // Add two probe clusters.
124*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = now,
125*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = DataRate::KilobitsPerSec(900),
126*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
127*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
128*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
129*d9f75844SAndroid Build Coastguard Worker 
130*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kProbeSize);
131*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(prober.is_probing());
132*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(prober.CurrentCluster(now)->probe_cluster_id, 0);
133*d9f75844SAndroid Build Coastguard Worker   // Advance to first probe time and indicate sent probe.
134*d9f75844SAndroid Build Coastguard Worker   now = std::max(now, prober.NextProbeTime(now));
135*d9f75844SAndroid Build Coastguard Worker   prober.ProbeSent(now, kProbeSize);
136*d9f75844SAndroid Build Coastguard Worker 
137*d9f75844SAndroid Build Coastguard Worker   // Advance time 1ms past timeout for the next probe.
138*d9f75844SAndroid Build Coastguard Worker   Timestamp next_probe_time = prober.NextProbeTime(now);
139*d9f75844SAndroid Build Coastguard Worker   EXPECT_GT(next_probe_time, now);
140*d9f75844SAndroid Build Coastguard Worker   now += next_probe_time - now + kMaxProbeDelay + TimeDelta::Millis(1);
141*d9f75844SAndroid Build Coastguard Worker 
142*d9f75844SAndroid Build Coastguard Worker   // Still indicates the time we wanted to probe at.
143*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(prober.NextProbeTime(now), next_probe_time);
144*d9f75844SAndroid Build Coastguard Worker   // First and only cluster removed due to timeout.
145*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.CurrentCluster(now).has_value());
146*d9f75844SAndroid Build Coastguard Worker }
147*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,LimitsNumberOfPendingProbeClusters)148*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, LimitsNumberOfPendingProbeClusters) {
149*d9f75844SAndroid Build Coastguard Worker   const FieldTrialBasedConfig config;
150*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
151*d9f75844SAndroid Build Coastguard Worker   const DataSize kProbeSize = DataSize::Bytes(1000);
152*d9f75844SAndroid Build Coastguard Worker   Timestamp now = Timestamp::Zero();
153*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = now,
154*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = DataRate::KilobitsPerSec(900),
155*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
156*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
157*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
158*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kProbeSize);
159*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(prober.is_probing());
160*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(prober.CurrentCluster(now)->probe_cluster_id, 0);
161*d9f75844SAndroid Build Coastguard Worker 
162*d9f75844SAndroid Build Coastguard Worker   for (int i = 1; i < 11; ++i) {
163*d9f75844SAndroid Build Coastguard Worker     prober.CreateProbeCluster(
164*d9f75844SAndroid Build Coastguard Worker         {.at_time = now,
165*d9f75844SAndroid Build Coastguard Worker          .target_data_rate = DataRate::KilobitsPerSec(900),
166*d9f75844SAndroid Build Coastguard Worker          .target_duration = TimeDelta::Millis(15),
167*d9f75844SAndroid Build Coastguard Worker          .target_probe_count = 5,
168*d9f75844SAndroid Build Coastguard Worker          .id = i});
169*d9f75844SAndroid Build Coastguard Worker     prober.OnIncomingPacket(kProbeSize);
170*d9f75844SAndroid Build Coastguard Worker   }
171*d9f75844SAndroid Build Coastguard Worker   // Expect some clusters has been dropped.
172*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(prober.is_probing());
173*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(prober.CurrentCluster(now)->probe_cluster_id, 5);
174*d9f75844SAndroid Build Coastguard Worker 
175*d9f75844SAndroid Build Coastguard Worker   Timestamp max_expected_probe_time = now + TimeDelta::Seconds(1);
176*d9f75844SAndroid Build Coastguard Worker   while (prober.is_probing() && now < max_expected_probe_time) {
177*d9f75844SAndroid Build Coastguard Worker     now = std::max(now, prober.NextProbeTime(now));
178*d9f75844SAndroid Build Coastguard Worker     prober.ProbeSent(now, kProbeSize);
179*d9f75844SAndroid Build Coastguard Worker   }
180*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
181*d9f75844SAndroid Build Coastguard Worker }
182*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,DoesntInitializeProbingForSmallPackets)183*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, DoesntInitializeProbingForSmallPackets) {
184*d9f75844SAndroid Build Coastguard Worker   const FieldTrialBasedConfig config;
185*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
186*d9f75844SAndroid Build Coastguard Worker   prober.SetEnabled(true);
187*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(prober.is_probing());
188*d9f75844SAndroid Build Coastguard Worker 
189*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = Timestamp::Zero(),
190*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = DataRate::KilobitsPerSec(1000),
191*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
192*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
193*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
194*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(DataSize::Bytes(100));
195*d9f75844SAndroid Build Coastguard Worker 
196*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
197*d9f75844SAndroid Build Coastguard Worker }
198*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,DoesInitializeProbingForSmallPacketsIfConfigured)199*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, DoesInitializeProbingForSmallPacketsIfConfigured) {
200*d9f75844SAndroid Build Coastguard Worker   const test::ExplicitKeyValueConfig config(
201*d9f75844SAndroid Build Coastguard Worker       "WebRTC-Bwe-ProbingBehavior/"
202*d9f75844SAndroid Build Coastguard Worker       "min_packet_size:0bytes/");
203*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
204*d9f75844SAndroid Build Coastguard Worker   prober.SetEnabled(true);
205*d9f75844SAndroid Build Coastguard Worker   ASSERT_FALSE(prober.is_probing());
206*d9f75844SAndroid Build Coastguard Worker 
207*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = Timestamp::Zero(),
208*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = DataRate::KilobitsPerSec(1000),
209*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
210*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
211*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
212*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(DataSize::Bytes(10));
213*d9f75844SAndroid Build Coastguard Worker 
214*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(prober.is_probing());
215*d9f75844SAndroid Build Coastguard Worker }
216*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,VerifyProbeSizeOnHighBitrate)217*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, VerifyProbeSizeOnHighBitrate) {
218*d9f75844SAndroid Build Coastguard Worker   const FieldTrialBasedConfig config;
219*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
220*d9f75844SAndroid Build Coastguard Worker 
221*d9f75844SAndroid Build Coastguard Worker   const DataRate kHighBitrate = DataRate::KilobitsPerSec(10000);  // 10 Mbps
222*d9f75844SAndroid Build Coastguard Worker 
223*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = Timestamp::Zero(),
224*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kHighBitrate,
225*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
226*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
227*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
228*d9f75844SAndroid Build Coastguard Worker   // Probe size should ensure a minimum of 1 ms interval.
229*d9f75844SAndroid Build Coastguard Worker   EXPECT_GT(prober.RecommendedMinProbeSize(),
230*d9f75844SAndroid Build Coastguard Worker             kHighBitrate * TimeDelta::Millis(1));
231*d9f75844SAndroid Build Coastguard Worker }
232*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,ProbeSizeCanBeSetWithFieldTrial)233*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, ProbeSizeCanBeSetWithFieldTrial) {
234*d9f75844SAndroid Build Coastguard Worker   const test::ExplicitKeyValueConfig trials(
235*d9f75844SAndroid Build Coastguard Worker       "WebRTC-Bwe-ProbingBehavior/min_probe_delta:20ms/");
236*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(trials);
237*d9f75844SAndroid Build Coastguard Worker   prober.SetEnabled(true);
238*d9f75844SAndroid Build Coastguard Worker 
239*d9f75844SAndroid Build Coastguard Worker   const DataRate kHighBitrate = DataRate::KilobitsPerSec(10000);  // 10 Mbps
240*d9f75844SAndroid Build Coastguard Worker 
241*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = Timestamp::Zero(),
242*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kHighBitrate,
243*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
244*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
245*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
246*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(prober.RecommendedMinProbeSize(),
247*d9f75844SAndroid Build Coastguard Worker             kHighBitrate * TimeDelta::Millis(20));
248*d9f75844SAndroid Build Coastguard Worker 
249*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(DataSize::Bytes(1000));
250*d9f75844SAndroid Build Coastguard Worker   // Next time to send probe should be "min_probe_delta" if the recommended
251*d9f75844SAndroid Build Coastguard Worker   // number of bytes has been sent.
252*d9f75844SAndroid Build Coastguard Worker   prober.ProbeSent(Timestamp::Zero(), prober.RecommendedMinProbeSize());
253*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(prober.NextProbeTime(Timestamp::Zero()),
254*d9f75844SAndroid Build Coastguard Worker             Timestamp::Zero() + TimeDelta::Millis(20));
255*d9f75844SAndroid Build Coastguard Worker }
256*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,MinumumNumberOfProbingPackets)257*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, MinumumNumberOfProbingPackets) {
258*d9f75844SAndroid Build Coastguard Worker   const FieldTrialBasedConfig config;
259*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
260*d9f75844SAndroid Build Coastguard Worker   // Even when probing at a low bitrate we expect a minimum number
261*d9f75844SAndroid Build Coastguard Worker   // of packets to be sent.
262*d9f75844SAndroid Build Coastguard Worker   const DataRate kBitrate = DataRate::KilobitsPerSec(100);
263*d9f75844SAndroid Build Coastguard Worker   const DataSize kPacketSize = DataSize::Bytes(1000);
264*d9f75844SAndroid Build Coastguard Worker 
265*d9f75844SAndroid Build Coastguard Worker   Timestamp now = Timestamp::Zero();
266*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = Timestamp::Zero(),
267*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kBitrate,
268*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
269*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
270*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
271*d9f75844SAndroid Build Coastguard Worker 
272*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kPacketSize);
273*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 5; ++i) {
274*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(prober.is_probing());
275*d9f75844SAndroid Build Coastguard Worker     prober.ProbeSent(now, kPacketSize);
276*d9f75844SAndroid Build Coastguard Worker   }
277*d9f75844SAndroid Build Coastguard Worker 
278*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
279*d9f75844SAndroid Build Coastguard Worker }
280*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,ScaleBytesUsedForProbing)281*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, ScaleBytesUsedForProbing) {
282*d9f75844SAndroid Build Coastguard Worker   const FieldTrialBasedConfig config;
283*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
284*d9f75844SAndroid Build Coastguard Worker   const DataRate kBitrate = DataRate::KilobitsPerSec(10000);  // 10 Mbps.
285*d9f75844SAndroid Build Coastguard Worker   const DataSize kPacketSize = DataSize::Bytes(1000);
286*d9f75844SAndroid Build Coastguard Worker   const DataSize kExpectedDataSent = kBitrate * TimeDelta::Millis(15);
287*d9f75844SAndroid Build Coastguard Worker 
288*d9f75844SAndroid Build Coastguard Worker   Timestamp now = Timestamp::Zero();
289*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = Timestamp::Zero(),
290*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kBitrate,
291*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
292*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
293*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
294*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kPacketSize);
295*d9f75844SAndroid Build Coastguard Worker   DataSize data_sent = DataSize::Zero();
296*d9f75844SAndroid Build Coastguard Worker   while (data_sent < kExpectedDataSent) {
297*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(prober.is_probing());
298*d9f75844SAndroid Build Coastguard Worker     prober.ProbeSent(now, kPacketSize);
299*d9f75844SAndroid Build Coastguard Worker     data_sent += kPacketSize;
300*d9f75844SAndroid Build Coastguard Worker   }
301*d9f75844SAndroid Build Coastguard Worker 
302*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
303*d9f75844SAndroid Build Coastguard Worker }
304*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,HighBitrateProbing)305*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, HighBitrateProbing) {
306*d9f75844SAndroid Build Coastguard Worker   const FieldTrialBasedConfig config;
307*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
308*d9f75844SAndroid Build Coastguard Worker   const DataRate kBitrate = DataRate::KilobitsPerSec(1000000);  // 1 Gbps.
309*d9f75844SAndroid Build Coastguard Worker   const DataSize kPacketSize = DataSize::Bytes(1000);
310*d9f75844SAndroid Build Coastguard Worker   const DataSize kExpectedDataSent = kBitrate * TimeDelta::Millis(15);
311*d9f75844SAndroid Build Coastguard Worker 
312*d9f75844SAndroid Build Coastguard Worker   Timestamp now = Timestamp::Zero();
313*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = Timestamp::Zero(),
314*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kBitrate,
315*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
316*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
317*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
318*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kPacketSize);
319*d9f75844SAndroid Build Coastguard Worker   DataSize data_sent = DataSize::Zero();
320*d9f75844SAndroid Build Coastguard Worker   while (data_sent < kExpectedDataSent) {
321*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(prober.is_probing());
322*d9f75844SAndroid Build Coastguard Worker     prober.ProbeSent(now, kPacketSize);
323*d9f75844SAndroid Build Coastguard Worker     data_sent += kPacketSize;
324*d9f75844SAndroid Build Coastguard Worker   }
325*d9f75844SAndroid Build Coastguard Worker 
326*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
327*d9f75844SAndroid Build Coastguard Worker }
328*d9f75844SAndroid Build Coastguard Worker 
TEST(BitrateProberTest,ProbeClusterTimeout)329*d9f75844SAndroid Build Coastguard Worker TEST(BitrateProberTest, ProbeClusterTimeout) {
330*d9f75844SAndroid Build Coastguard Worker   const FieldTrialBasedConfig config;
331*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober(config);
332*d9f75844SAndroid Build Coastguard Worker   const DataRate kBitrate = DataRate::KilobitsPerSec(300);
333*d9f75844SAndroid Build Coastguard Worker   const DataSize kSmallPacketSize = DataSize::Bytes(20);
334*d9f75844SAndroid Build Coastguard Worker   // Expecting two probe clusters of 5 packets each.
335*d9f75844SAndroid Build Coastguard Worker   const DataSize kExpectedDataSent = kSmallPacketSize * 2 * 5;
336*d9f75844SAndroid Build Coastguard Worker   const TimeDelta kTimeout = TimeDelta::Millis(5000);
337*d9f75844SAndroid Build Coastguard Worker 
338*d9f75844SAndroid Build Coastguard Worker   Timestamp now = Timestamp::Zero();
339*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = now,
340*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kBitrate,
341*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
342*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
343*d9f75844SAndroid Build Coastguard Worker                              .id = 0});
344*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kSmallPacketSize);
345*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
346*d9f75844SAndroid Build Coastguard Worker   now += kTimeout;
347*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = now,
348*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kBitrate / 10,
349*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
350*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
351*d9f75844SAndroid Build Coastguard Worker                              .id = 1});
352*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kSmallPacketSize);
353*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
354*d9f75844SAndroid Build Coastguard Worker   now += TimeDelta::Millis(1);
355*d9f75844SAndroid Build Coastguard Worker   prober.CreateProbeCluster({.at_time = now,
356*d9f75844SAndroid Build Coastguard Worker                              .target_data_rate = kBitrate / 10,
357*d9f75844SAndroid Build Coastguard Worker                              .target_duration = TimeDelta::Millis(15),
358*d9f75844SAndroid Build Coastguard Worker                              .target_probe_count = 5,
359*d9f75844SAndroid Build Coastguard Worker                              .id = 2});
360*d9f75844SAndroid Build Coastguard Worker   prober.OnIncomingPacket(kSmallPacketSize);
361*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(prober.is_probing());
362*d9f75844SAndroid Build Coastguard Worker   DataSize data_sent = DataSize::Zero();
363*d9f75844SAndroid Build Coastguard Worker   while (data_sent < kExpectedDataSent) {
364*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(prober.is_probing());
365*d9f75844SAndroid Build Coastguard Worker     prober.ProbeSent(now, kSmallPacketSize);
366*d9f75844SAndroid Build Coastguard Worker     data_sent += kSmallPacketSize;
367*d9f75844SAndroid Build Coastguard Worker   }
368*d9f75844SAndroid Build Coastguard Worker 
369*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(prober.is_probing());
370*d9f75844SAndroid Build Coastguard Worker }
371*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
372