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/gtest.h"
16 
17 namespace webrtc {
18 
TEST(BitrateProberTest,VerifyStatesAndTimeBetweenProbes)19 TEST(BitrateProberTest, VerifyStatesAndTimeBetweenProbes) {
20   const FieldTrialBasedConfig config;
21   BitrateProber prober(config);
22   EXPECT_FALSE(prober.is_probing());
23 
24   Timestamp now = Timestamp::Millis(0);
25   const Timestamp start_time = now;
26   EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
27 
28   const DataRate kTestBitrate1 = DataRate::KilobitsPerSec(900);
29   const DataRate kTestBitrate2 = DataRate::KilobitsPerSec(1800);
30   const int kClusterSize = 5;
31   const int kProbeSize = 1000;
32   const TimeDelta kMinProbeDuration = TimeDelta::Millis(15);
33 
34   prober.CreateProbeCluster(kTestBitrate1, now, 0);
35   prober.CreateProbeCluster(kTestBitrate2, now, 1);
36   EXPECT_FALSE(prober.is_probing());
37 
38   prober.OnIncomingPacket(kProbeSize);
39   EXPECT_TRUE(prober.is_probing());
40   EXPECT_EQ(0, prober.CurrentCluster().probe_cluster_id);
41 
42   // First packet should probe as soon as possible.
43   EXPECT_EQ(Timestamp::MinusInfinity(), prober.NextProbeTime(now));
44 
45   for (int i = 0; i < kClusterSize; ++i) {
46     now = std::max(now, prober.NextProbeTime(now));
47     EXPECT_EQ(now, std::max(now, prober.NextProbeTime(now)));
48     EXPECT_EQ(0, prober.CurrentCluster().probe_cluster_id);
49     prober.ProbeSent(now, kProbeSize);
50   }
51 
52   EXPECT_GE(now - start_time, kMinProbeDuration);
53   // Verify that the actual bitrate is withing 10% of the target.
54   DataRate bitrate =
55       DataSize::Bytes(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().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 = DataSize::Bytes(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 
84   Timestamp now = Timestamp::Zero();
85   EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
86 
87   prober.CreateProbeCluster(DataRate::KilobitsPerSec(900), now, 0);
88   EXPECT_FALSE(prober.is_probing());
89 
90   prober.OnIncomingPacket(1000);
91   EXPECT_TRUE(prober.is_probing());
92   EXPECT_EQ(now, std::max(now, prober.NextProbeTime(now)));
93   prober.ProbeSent(now, 1000);
94   // Let time pass, no large enough packets put into prober.
95   now += TimeDelta::Seconds(6);
96   EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
97   // Check that legacy behaviour where prober is reset in TimeUntilNextProbe is
98   // no longer there. Probes are no longer retried if they are timed out.
99   prober.OnIncomingPacket(1000);
100   EXPECT_EQ(prober.NextProbeTime(now), Timestamp::PlusInfinity());
101 }
102 
TEST(BitrateProberTest,DoesntInitializeProbingForSmallPackets)103 TEST(BitrateProberTest, DoesntInitializeProbingForSmallPackets) {
104   const FieldTrialBasedConfig config;
105   BitrateProber prober(config);
106 
107   prober.SetEnabled(true);
108   EXPECT_FALSE(prober.is_probing());
109 
110   prober.OnIncomingPacket(100);
111   EXPECT_FALSE(prober.is_probing());
112 }
113 
TEST(BitrateProberTest,VerifyProbeSizeOnHighBitrate)114 TEST(BitrateProberTest, VerifyProbeSizeOnHighBitrate) {
115   const FieldTrialBasedConfig config;
116   BitrateProber prober(config);
117 
118   const DataRate kHighBitrate = DataRate::KilobitsPerSec(10000);  // 10 Mbps
119 
120   prober.CreateProbeCluster(kHighBitrate, Timestamp::Millis(0),
121                             /*cluster_id=*/0);
122   // Probe size should ensure a minimum of 1 ms interval.
123   EXPECT_GT(prober.RecommendedMinProbeSize(),
124             (kHighBitrate * TimeDelta::Millis(1)).bytes<size_t>());
125 }
126 
TEST(BitrateProberTest,MinumumNumberOfProbingPackets)127 TEST(BitrateProberTest, MinumumNumberOfProbingPackets) {
128   const FieldTrialBasedConfig config;
129   BitrateProber prober(config);
130   // Even when probing at a low bitrate we expect a minimum number
131   // of packets to be sent.
132   const DataRate kBitrate = DataRate::KilobitsPerSec(100);
133   const int kPacketSizeBytes = 1000;
134 
135   Timestamp now = Timestamp::Millis(0);
136   prober.CreateProbeCluster(kBitrate, now, 0);
137   prober.OnIncomingPacket(kPacketSizeBytes);
138   for (int i = 0; i < 5; ++i) {
139     EXPECT_TRUE(prober.is_probing());
140     prober.ProbeSent(now, kPacketSizeBytes);
141   }
142 
143   EXPECT_FALSE(prober.is_probing());
144 }
145 
TEST(BitrateProberTest,ScaleBytesUsedForProbing)146 TEST(BitrateProberTest, ScaleBytesUsedForProbing) {
147   const FieldTrialBasedConfig config;
148   BitrateProber prober(config);
149   const DataRate kBitrate = DataRate::KilobitsPerSec(10000);  // 10 Mbps.
150   const int kPacketSizeBytes = 1000;
151   const int kExpectedBytesSent = (kBitrate * TimeDelta::Millis(15)).bytes();
152 
153   Timestamp now = Timestamp::Millis(0);
154   prober.CreateProbeCluster(kBitrate, now, /*cluster_id=*/0);
155   prober.OnIncomingPacket(kPacketSizeBytes);
156   int bytes_sent = 0;
157   while (bytes_sent < kExpectedBytesSent) {
158     ASSERT_TRUE(prober.is_probing());
159     prober.ProbeSent(now, kPacketSizeBytes);
160     bytes_sent += kPacketSizeBytes;
161   }
162 
163   EXPECT_FALSE(prober.is_probing());
164 }
165 
TEST(BitrateProberTest,HighBitrateProbing)166 TEST(BitrateProberTest, HighBitrateProbing) {
167   const FieldTrialBasedConfig config;
168   BitrateProber prober(config);
169   const DataRate kBitrate = DataRate::KilobitsPerSec(1000000);  // 1 Gbps.
170   const int kPacketSizeBytes = 1000;
171   const int kExpectedBytesSent = (kBitrate * TimeDelta::Millis(15)).bytes();
172 
173   Timestamp now = Timestamp::Millis(0);
174   prober.CreateProbeCluster(kBitrate, now, 0);
175   prober.OnIncomingPacket(kPacketSizeBytes);
176   int bytes_sent = 0;
177   while (bytes_sent < kExpectedBytesSent) {
178     ASSERT_TRUE(prober.is_probing());
179     prober.ProbeSent(now, kPacketSizeBytes);
180     bytes_sent += kPacketSizeBytes;
181   }
182 
183   EXPECT_FALSE(prober.is_probing());
184 }
185 
TEST(BitrateProberTest,ProbeClusterTimeout)186 TEST(BitrateProberTest, ProbeClusterTimeout) {
187   const FieldTrialBasedConfig config;
188   BitrateProber prober(config);
189   const DataRate kBitrate = DataRate::KilobitsPerSec(300);
190   const int kSmallPacketSize = 20;
191   // Expecting two probe clusters of 5 packets each.
192   const int kExpectedBytesSent = 20 * 2 * 5;
193   const TimeDelta kTimeout = TimeDelta::Millis(5000);
194 
195   Timestamp now = Timestamp::Millis(0);
196   prober.CreateProbeCluster(kBitrate, now, /*cluster_id=*/0);
197   prober.OnIncomingPacket(kSmallPacketSize);
198   EXPECT_FALSE(prober.is_probing());
199   now += kTimeout;
200   prober.CreateProbeCluster(kBitrate / 10, now, /*cluster_id=*/1);
201   prober.OnIncomingPacket(kSmallPacketSize);
202   EXPECT_FALSE(prober.is_probing());
203   now += TimeDelta::Millis(1);
204   prober.CreateProbeCluster(kBitrate / 10, now, /*cluster_id=*/2);
205   prober.OnIncomingPacket(kSmallPacketSize);
206   EXPECT_TRUE(prober.is_probing());
207   int bytes_sent = 0;
208   while (bytes_sent < kExpectedBytesSent) {
209     ASSERT_TRUE(prober.is_probing());
210     prober.ProbeSent(now, kSmallPacketSize);
211     bytes_sent += kSmallPacketSize;
212   }
213 
214   EXPECT_FALSE(prober.is_probing());
215 }
216 }  // namespace webrtc
217