summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/rtc_base/frequency_tracker_unittest.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/rtc_base/frequency_tracker_unittest.cc
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/rtc_base/frequency_tracker_unittest.cc')
-rw-r--r--third_party/libwebrtc/rtc_base/frequency_tracker_unittest.cc203
1 files changed, 203 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_base/frequency_tracker_unittest.cc b/third_party/libwebrtc/rtc_base/frequency_tracker_unittest.cc
new file mode 100644
index 0000000000..00788c3ee8
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/frequency_tracker_unittest.cc
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2023 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 "rtc_base/frequency_tracker.h"
+
+#include <cstdlib>
+#include <limits>
+
+#include "absl/types/optional.h"
+#include "api/units/frequency.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::AllOf;
+using ::testing::Gt;
+using ::testing::Lt;
+
+constexpr TimeDelta kWindow = TimeDelta::Millis(500);
+constexpr TimeDelta kEpsilon = TimeDelta::Millis(1);
+
+TEST(FrequencyTrackerTest, ReturnsNulloptInitially) {
+ Timestamp now = Timestamp::Seconds(12'345);
+ FrequencyTracker stats(kWindow);
+
+ EXPECT_EQ(stats.Rate(now), absl::nullopt);
+}
+
+TEST(FrequencyTrackerTest, ReturnsNulloptAfterSingleDataPoint) {
+ Timestamp now = Timestamp::Seconds(12'345);
+ FrequencyTracker stats(kWindow);
+
+ stats.Update(now);
+ now += TimeDelta::Millis(10);
+
+ EXPECT_EQ(stats.Rate(now), absl::nullopt);
+}
+
+TEST(FrequencyTrackerTest, ReturnsRateAfterTwoMeasurements) {
+ Timestamp now = Timestamp::Seconds(12'345);
+ FrequencyTracker stats(kWindow);
+
+ stats.Update(now);
+ now += TimeDelta::Millis(1);
+ stats.Update(now);
+
+ // 1 event per 1 ms ~= 1'000 events per second.
+ EXPECT_EQ(stats.Rate(now), Frequency::Hertz(1'000));
+}
+
+TEST(FrequencyTrackerTest, MeasuresConstantRate) {
+ const Timestamp start = Timestamp::Seconds(12'345);
+ const TimeDelta kInterval = TimeDelta::Millis(10);
+ const Frequency kConstantRate = 1 / kInterval;
+
+ Timestamp now = start;
+ FrequencyTracker stats(kWindow);
+
+ stats.Update(now);
+ Frequency last_error = Frequency::PlusInfinity();
+ for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kInterval) {
+ SCOPED_TRACE(i);
+ now += kInterval;
+ stats.Update(now);
+
+ // Until window is full, rate is measured over a smaller window and might
+ // look larger than the constant rate.
+ absl::optional<Frequency> rate = stats.Rate(now);
+ ASSERT_GE(rate, kConstantRate);
+
+ // Expect the estimation error to decrease as the window is extended.
+ Frequency error = *rate - kConstantRate;
+ EXPECT_LE(error, last_error);
+ last_error = error;
+ }
+
+ // Once window is full, rate measurment should be stable.
+ for (TimeDelta i = TimeDelta::Zero(); i < kInterval;
+ i += TimeDelta::Millis(1)) {
+ SCOPED_TRACE(i);
+ EXPECT_EQ(stats.Rate(now + i), kConstantRate);
+ }
+}
+
+TEST(FrequencyTrackerTest, CanMeasureFractionalRate) {
+ const TimeDelta kInterval = TimeDelta::Millis(134);
+ Timestamp now = Timestamp::Seconds(12'345);
+ // FrequencyTracker counts number of events in the window, thus when window is
+ // fraction of 1 second, number of events per second would always be integer.
+ const TimeDelta window = TimeDelta::Seconds(2);
+
+ FrequencyTracker framerate(window);
+ framerate.Update(now);
+ for (TimeDelta i = TimeDelta::Zero(); i < window; i += kInterval) {
+ now += kInterval;
+ framerate.Update(now);
+ }
+
+ // Should be aproximitly 7.5 fps
+ EXPECT_THAT(framerate.Rate(now),
+ AllOf(Gt(Frequency::Hertz(7)), Lt(Frequency::Hertz(8))));
+}
+
+TEST(FrequencyTrackerTest, IncreasingThenDecreasingRate) {
+ const int64_t kLargeSize = 1'500;
+ const int64_t kSmallSize = 300;
+ const TimeDelta kLargeInterval = TimeDelta::Millis(10);
+ const TimeDelta kSmallInterval = TimeDelta::Millis(2);
+
+ Timestamp now = Timestamp::Seconds(12'345);
+ FrequencyTracker stats(kWindow);
+
+ stats.Update(kLargeSize, now);
+ for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kLargeInterval) {
+ SCOPED_TRACE(i);
+ now += kLargeInterval;
+ stats.Update(kLargeSize, now);
+ }
+ absl::optional<Frequency> last_rate = stats.Rate(now);
+ EXPECT_EQ(last_rate, kLargeSize / kLargeInterval);
+
+ // Decrease rate with smaller measurments.
+ for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kLargeInterval) {
+ SCOPED_TRACE(i);
+ now += kLargeInterval;
+ stats.Update(kSmallSize, now);
+
+ absl::optional<Frequency> rate = stats.Rate(now);
+ EXPECT_LT(rate, last_rate);
+
+ last_rate = rate;
+ }
+ EXPECT_EQ(last_rate, kSmallSize / kLargeInterval);
+
+ // Increase rate with more frequent measurments.
+ for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kSmallInterval) {
+ SCOPED_TRACE(i);
+ now += kSmallInterval;
+ stats.Update(kSmallSize, now);
+
+ absl::optional<Frequency> rate = stats.Rate(now);
+ EXPECT_GE(rate, last_rate);
+
+ last_rate = rate;
+ }
+ EXPECT_EQ(last_rate, kSmallSize / kSmallInterval);
+}
+
+TEST(FrequencyTrackerTest, ResetAfterSilence) {
+ const TimeDelta kInterval = TimeDelta::Millis(10);
+ const int64_t kPixels = 640 * 360;
+
+ Timestamp now = Timestamp::Seconds(12'345);
+ FrequencyTracker pixel_rate(kWindow);
+
+ // Feed data until window has been filled.
+ pixel_rate.Update(kPixels, now);
+ for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kInterval) {
+ now += kInterval;
+ pixel_rate.Update(kPixels, now);
+ }
+ ASSERT_GT(pixel_rate.Rate(now), Frequency::Zero());
+
+ now += kWindow + kEpsilon;
+ // Silence over window size should trigger auto reset for coming sample.
+ EXPECT_EQ(pixel_rate.Rate(now), absl::nullopt);
+ pixel_rate.Update(kPixels, now);
+ // Single measurment after reset is not enough to estimate the rate.
+ EXPECT_EQ(pixel_rate.Rate(now), absl::nullopt);
+
+ // Manual reset, add the same check again.
+ pixel_rate.Reset();
+ EXPECT_EQ(pixel_rate.Rate(now), absl::nullopt);
+ now += kInterval;
+ pixel_rate.Update(kPixels, now);
+ EXPECT_EQ(pixel_rate.Rate(now), absl::nullopt);
+}
+
+TEST(FrequencyTrackerTest, ReturnsNulloptWhenOverflows) {
+ Timestamp now = Timestamp::Seconds(12'345);
+ FrequencyTracker stats(kWindow);
+
+ int64_t very_large_number = std::numeric_limits<int64_t>::max();
+ stats.Update(very_large_number, now);
+ now += kEpsilon;
+ stats.Update(very_large_number, now);
+
+ EXPECT_EQ(stats.Rate(now), absl::nullopt);
+}
+
+} // namespace
+} // namespace webrtc