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