blob: 95d26593cbddb91fc6325f52f402479a8f903837 [file] [log] [blame]
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <limits>
#include "modules/pacing/bitrate_prober.h"
#include "test/gtest.h"
namespace webrtc {
TEST(BitrateProberTest, VerifyStatesAndTimeBetweenProbes) {
BitrateProber prober;
EXPECT_FALSE(prober.IsProbing());
int64_t now_ms = 0;
EXPECT_EQ(-1, prober.TimeUntilNextProbe(now_ms));
const int kTestBitrate1 = 900000;
const int kTestBitrate2 = 1800000;
const int kClusterSize = 5;
const int kProbeSize = 1000;
const int kMinProbeDurationMs = 15;
prober.CreateProbeCluster(kTestBitrate1, now_ms);
prober.CreateProbeCluster(kTestBitrate2, now_ms);
EXPECT_FALSE(prober.IsProbing());
prober.OnIncomingPacket(kProbeSize);
EXPECT_TRUE(prober.IsProbing());
EXPECT_EQ(0, prober.CurrentCluster().probe_cluster_id);
// First packet should probe as soon as possible.
EXPECT_EQ(0, prober.TimeUntilNextProbe(now_ms));
for (int i = 0; i < kClusterSize; ++i) {
now_ms += prober.TimeUntilNextProbe(now_ms);
EXPECT_EQ(0, prober.TimeUntilNextProbe(now_ms));
EXPECT_EQ(0, prober.CurrentCluster().probe_cluster_id);
prober.ProbeSent(now_ms, kProbeSize);
}
EXPECT_GE(now_ms, kMinProbeDurationMs);
// Verify that the actual bitrate is withing 10% of the target.
double bitrate = kProbeSize * (kClusterSize - 1) * 8 * 1000.0 / now_ms;
EXPECT_GT(bitrate, kTestBitrate1 * 0.9);
EXPECT_LT(bitrate, kTestBitrate1 * 1.1);
now_ms += prober.TimeUntilNextProbe(now_ms);
int64_t probe2_started = now_ms;
for (int i = 0; i < kClusterSize; ++i) {
now_ms += prober.TimeUntilNextProbe(now_ms);
EXPECT_EQ(0, prober.TimeUntilNextProbe(now_ms));
EXPECT_EQ(1, prober.CurrentCluster().probe_cluster_id);
prober.ProbeSent(now_ms, kProbeSize);
}
// Verify that the actual bitrate is withing 10% of the target.
int duration = now_ms - probe2_started;
EXPECT_GE(duration, kMinProbeDurationMs);
bitrate = kProbeSize * (kClusterSize - 1) * 8 * 1000.0 / duration;
EXPECT_GT(bitrate, kTestBitrate2 * 0.9);
EXPECT_LT(bitrate, kTestBitrate2 * 1.1);
EXPECT_EQ(-1, prober.TimeUntilNextProbe(now_ms));
EXPECT_FALSE(prober.IsProbing());
}
TEST(BitrateProberTest, DoesntProbeWithoutRecentPackets) {
BitrateProber prober;
EXPECT_FALSE(prober.IsProbing());
int64_t now_ms = 0;
EXPECT_EQ(-1, prober.TimeUntilNextProbe(now_ms));
prober.CreateProbeCluster(900000, now_ms);
EXPECT_FALSE(prober.IsProbing());
prober.OnIncomingPacket(1000);
EXPECT_TRUE(prober.IsProbing());
EXPECT_EQ(0, prober.TimeUntilNextProbe(now_ms));
prober.ProbeSent(now_ms, 1000);
// Let time pass, no large enough packets put into prober.
now_ms += 6000;
EXPECT_EQ(-1, prober.TimeUntilNextProbe(now_ms));
// Check that legacy behaviour where prober is reset in TimeUntilNextProbe is
// no longer there. Probes are no longer retried if they are timed out.
prober.OnIncomingPacket(1000);
EXPECT_EQ(-1, prober.TimeUntilNextProbe(now_ms));
}
TEST(BitrateProberTest, DoesntInitializeProbingForSmallPackets) {
BitrateProber prober;
prober.SetEnabled(true);
EXPECT_FALSE(prober.IsProbing());
prober.OnIncomingPacket(100);
EXPECT_FALSE(prober.IsProbing());
}
TEST(BitrateProberTest, VerifyProbeSizeOnHighBitrate) {
BitrateProber prober;
constexpr unsigned kHighBitrateBps = 10000000; // 10 Mbps
prober.CreateProbeCluster(kHighBitrateBps, 0);
// Probe size should ensure a minimum of 1 ms interval.
EXPECT_GT(prober.RecommendedMinProbeSize(), kHighBitrateBps / 8000);
}
TEST(BitrateProberTest, MinumumNumberOfProbingPackets) {
BitrateProber prober;
// Even when probing at a low bitrate we expect a minimum number
// of packets to be sent.
constexpr int kBitrateBps = 100000; // 100 kbps
constexpr int kPacketSizeBytes = 1000;
prober.CreateProbeCluster(kBitrateBps, 0);
prober.OnIncomingPacket(kPacketSizeBytes);
for (int i = 0; i < 5; ++i) {
EXPECT_TRUE(prober.IsProbing());
prober.ProbeSent(0, kPacketSizeBytes);
}
EXPECT_FALSE(prober.IsProbing());
}
TEST(BitrateProberTest, ScaleBytesUsedForProbing) {
BitrateProber prober;
constexpr int kBitrateBps = 10000000; // 10 Mbps
constexpr int kPacketSizeBytes = 1000;
constexpr int kExpectedBytesSent = kBitrateBps * 15 / 8000;
prober.CreateProbeCluster(kBitrateBps, 0);
prober.OnIncomingPacket(kPacketSizeBytes);
int bytes_sent = 0;
while (bytes_sent < kExpectedBytesSent) {
ASSERT_TRUE(prober.IsProbing());
prober.ProbeSent(0, kPacketSizeBytes);
bytes_sent += kPacketSizeBytes;
}
EXPECT_FALSE(prober.IsProbing());
}
TEST(BitrateProberTest, HighBitrateProbing) {
BitrateProber prober;
constexpr int kBitrateBps = 1000000000; // 1 Gbps.
constexpr int kPacketSizeBytes = 1000;
constexpr int kExpectedBytesSent = (kBitrateBps / 8000) * 15;
prober.CreateProbeCluster(kBitrateBps, 0);
prober.OnIncomingPacket(kPacketSizeBytes);
int bytes_sent = 0;
while (bytes_sent < kExpectedBytesSent) {
ASSERT_TRUE(prober.IsProbing());
prober.ProbeSent(0, kPacketSizeBytes);
bytes_sent += kPacketSizeBytes;
}
EXPECT_FALSE(prober.IsProbing());
}
TEST(BitrateProberTest, ProbeClusterTimeout) {
BitrateProber prober;
constexpr int kBitrateBps = 300000; // 300 kbps
constexpr int kSmallPacketSize = 20;
// Expecting two probe clusters of 5 packets each.
constexpr int kExpectedBytesSent = 20 * 2 * 5;
constexpr int64_t kTimeoutMs = 5000;
int64_t now_ms = 0;
prober.CreateProbeCluster(kBitrateBps, now_ms);
prober.OnIncomingPacket(kSmallPacketSize);
EXPECT_FALSE(prober.IsProbing());
now_ms += kTimeoutMs;
prober.CreateProbeCluster(kBitrateBps / 10, now_ms);
prober.OnIncomingPacket(kSmallPacketSize);
EXPECT_FALSE(prober.IsProbing());
now_ms += 1;
prober.CreateProbeCluster(kBitrateBps / 10, now_ms);
prober.OnIncomingPacket(kSmallPacketSize);
EXPECT_TRUE(prober.IsProbing());
int bytes_sent = 0;
while (bytes_sent < kExpectedBytesSent) {
ASSERT_TRUE(prober.IsProbing());
prober.ProbeSent(0, kSmallPacketSize);
bytes_sent += kSmallPacketSize;
}
EXPECT_FALSE(prober.IsProbing());
}
} // namespace webrtc