mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-15 06:40:43 +01:00

Bug: webrtc:42226242 Change-Id: Ib59078d67af20fa44d79d1a9338b1a3ca6e4c6d2 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/354463 Auto-Submit: Björn Terelius <terelius@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42492}
229 lines
7.7 KiB
C++
229 lines
7.7 KiB
C++
/*
|
|
* Copyright 2019 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/numerics/event_based_exponential_moving_average.h"
|
|
|
|
#include <cmath>
|
|
#include <cstdint>
|
|
#include <limits>
|
|
|
|
#include "test/gtest.h"
|
|
|
|
namespace {
|
|
|
|
constexpr int kHalfTime = 500;
|
|
constexpr double kError = 0.1;
|
|
|
|
} // namespace
|
|
|
|
namespace rtc {
|
|
|
|
TEST(EventBasedExponentialMovingAverageTest, NoValue) {
|
|
EventBasedExponentialMovingAverage average(kHalfTime);
|
|
|
|
EXPECT_TRUE(std::isnan(average.GetAverage()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(), average.GetVariance());
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
average.GetConfidenceInterval());
|
|
}
|
|
|
|
TEST(EventBasedExponentialMovingAverageTest, FirstValue) {
|
|
EventBasedExponentialMovingAverage average(kHalfTime);
|
|
|
|
int64_t time = 23;
|
|
constexpr int value = 1000;
|
|
average.AddSample(time, value);
|
|
EXPECT_NEAR(value, average.GetAverage(), kError);
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(), average.GetVariance());
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
average.GetConfidenceInterval());
|
|
}
|
|
|
|
TEST(EventBasedExponentialMovingAverageTest, Half) {
|
|
EventBasedExponentialMovingAverage average(kHalfTime);
|
|
|
|
int64_t time = 23;
|
|
constexpr int value = 1000;
|
|
average.AddSample(time, value);
|
|
average.AddSample(time + kHalfTime, 0);
|
|
EXPECT_NEAR(666.7, average.GetAverage(), kError);
|
|
EXPECT_NEAR(1000000, average.GetVariance(), kError);
|
|
EXPECT_NEAR(1460.9, average.GetConfidenceInterval(), kError);
|
|
}
|
|
|
|
TEST(EventBasedExponentialMovingAverageTest, Same) {
|
|
EventBasedExponentialMovingAverage average(kHalfTime);
|
|
|
|
int64_t time = 23;
|
|
constexpr int value = 1000;
|
|
average.AddSample(time, value);
|
|
average.AddSample(time + kHalfTime, value);
|
|
EXPECT_NEAR(value, average.GetAverage(), kError);
|
|
EXPECT_NEAR(0, average.GetVariance(), kError);
|
|
EXPECT_NEAR(0, average.GetConfidenceInterval(), kError);
|
|
}
|
|
|
|
TEST(EventBasedExponentialMovingAverageTest, Almost100) {
|
|
EventBasedExponentialMovingAverage average(kHalfTime);
|
|
|
|
int64_t time = 23;
|
|
constexpr int value = 100;
|
|
average.AddSample(time + 0 * kHalfTime, value - 10);
|
|
average.AddSample(time + 1 * kHalfTime, value + 10);
|
|
average.AddSample(time + 2 * kHalfTime, value - 15);
|
|
average.AddSample(time + 3 * kHalfTime, value + 15);
|
|
EXPECT_NEAR(100.2, average.GetAverage(), kError);
|
|
EXPECT_NEAR(372.6, average.GetVariance(), kError);
|
|
EXPECT_NEAR(19.7, average.GetConfidenceInterval(), kError); // 100 +/- 20
|
|
|
|
average.AddSample(time + 4 * kHalfTime, value);
|
|
average.AddSample(time + 5 * kHalfTime, value);
|
|
average.AddSample(time + 6 * kHalfTime, value);
|
|
average.AddSample(time + 7 * kHalfTime, value);
|
|
EXPECT_NEAR(100.0, average.GetAverage(), kError);
|
|
EXPECT_NEAR(73.6, average.GetVariance(), kError);
|
|
EXPECT_NEAR(7.6, average.GetConfidenceInterval(), kError); // 100 +/- 7
|
|
}
|
|
|
|
// Test that getting a value at X and another at X+1
|
|
// is almost the same as getting another at X and a value at X+1.
|
|
TEST(EventBasedExponentialMovingAverageTest, AlmostSameTime) {
|
|
int64_t time = 23;
|
|
constexpr int value = 100;
|
|
|
|
{
|
|
EventBasedExponentialMovingAverage average(kHalfTime);
|
|
average.AddSample(time + 0, value);
|
|
average.AddSample(time + 1, 0);
|
|
EXPECT_NEAR(50, average.GetAverage(), kError);
|
|
EXPECT_NEAR(10000, average.GetVariance(), kError);
|
|
EXPECT_NEAR(138.6, average.GetConfidenceInterval(),
|
|
kError); // 50 +/- 138.6
|
|
}
|
|
|
|
{
|
|
EventBasedExponentialMovingAverage average(kHalfTime);
|
|
average.AddSample(time + 0, 0);
|
|
average.AddSample(time + 1, 100);
|
|
EXPECT_NEAR(50, average.GetAverage(), kError);
|
|
EXPECT_NEAR(10000, average.GetVariance(), kError);
|
|
EXPECT_NEAR(138.6, average.GetConfidenceInterval(),
|
|
kError); // 50 +/- 138.6
|
|
}
|
|
}
|
|
|
|
// This test shows behavior of estimator with a half_time of 100.
|
|
// It is unclear if these set of observations are representative
|
|
// of any real world scenarios.
|
|
TEST(EventBasedExponentialMovingAverageTest, NonUniformSamplesHalftime100) {
|
|
int64_t time = 23;
|
|
constexpr int value = 100;
|
|
|
|
{
|
|
// The observations at 100 and 101, are significantly close in
|
|
// time that the estimator returns approx. the average.
|
|
EventBasedExponentialMovingAverage average(100);
|
|
average.AddSample(time + 0, value);
|
|
average.AddSample(time + 100, value);
|
|
average.AddSample(time + 101, 0);
|
|
EXPECT_NEAR(50.2, average.GetAverage(), kError);
|
|
EXPECT_NEAR(86.2, average.GetConfidenceInterval(), kError); // 50 +/- 86
|
|
}
|
|
|
|
{
|
|
EventBasedExponentialMovingAverage average(100);
|
|
average.AddSample(time + 0, value);
|
|
average.AddSample(time + 1, value);
|
|
average.AddSample(time + 100, 0);
|
|
EXPECT_NEAR(66.5, average.GetAverage(), kError);
|
|
EXPECT_NEAR(65.4, average.GetConfidenceInterval(), kError); // 66 +/- 65
|
|
}
|
|
|
|
{
|
|
EventBasedExponentialMovingAverage average(100);
|
|
for (int i = 0; i < 10; i++) {
|
|
average.AddSample(time + i, value);
|
|
}
|
|
average.AddSample(time + 100, 0);
|
|
EXPECT_NEAR(65.3, average.GetAverage(), kError);
|
|
EXPECT_NEAR(59.1, average.GetConfidenceInterval(), kError); // 55 +/- 59
|
|
}
|
|
|
|
{
|
|
EventBasedExponentialMovingAverage average(100);
|
|
average.AddSample(time + 0, 100);
|
|
for (int i = 90; i <= 100; i++) {
|
|
average.AddSample(time + i, 0);
|
|
}
|
|
EXPECT_NEAR(0.05, average.GetAverage(), kError);
|
|
EXPECT_NEAR(4.9, average.GetConfidenceInterval(), kError); // 0 +/- 5
|
|
}
|
|
}
|
|
|
|
TEST(EventBasedExponentialMovingAverageTest, Reset) {
|
|
constexpr int64_t time = 23;
|
|
constexpr int value = 100;
|
|
|
|
EventBasedExponentialMovingAverage average(100);
|
|
EXPECT_TRUE(std::isnan(average.GetAverage()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(), average.GetVariance());
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
average.GetConfidenceInterval());
|
|
|
|
average.AddSample(time + 0, value);
|
|
average.AddSample(time + 100, value);
|
|
average.AddSample(time + 101, 0);
|
|
EXPECT_FALSE(std::isnan(average.GetAverage()));
|
|
|
|
average.Reset();
|
|
EXPECT_TRUE(std::isnan(average.GetAverage()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(), average.GetVariance());
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
average.GetConfidenceInterval());
|
|
}
|
|
|
|
// Test that SetHalfTime modifies behavior and resets average.
|
|
TEST(EventBasedExponentialMovingAverageTest, SetHalfTime) {
|
|
constexpr int64_t time = 23;
|
|
constexpr int value = 100;
|
|
|
|
EventBasedExponentialMovingAverage average(100);
|
|
|
|
average.AddSample(time + 0, value);
|
|
average.AddSample(time + 100, 0);
|
|
EXPECT_NEAR(66.7, average.GetAverage(), kError);
|
|
|
|
average.SetHalfTime(1000);
|
|
EXPECT_TRUE(std::isnan(average.GetAverage()));
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(), average.GetVariance());
|
|
EXPECT_EQ(std::numeric_limits<double>::infinity(),
|
|
average.GetConfidenceInterval());
|
|
|
|
average.AddSample(time + 0, value);
|
|
average.AddSample(time + 100, 0);
|
|
EXPECT_NEAR(51.7, average.GetAverage(), kError);
|
|
}
|
|
|
|
TEST(EventBasedExponentialMovingAverageTest, SimultaneousSamples) {
|
|
constexpr int64_t time = 23;
|
|
constexpr int value = 100;
|
|
|
|
EventBasedExponentialMovingAverage average(100);
|
|
|
|
average.AddSample(time, value);
|
|
// This should really NOT be supported,
|
|
// i.e 2 samples with same timestamp.
|
|
// But there are tests running with simulated clock
|
|
// that produce this.
|
|
// TODO(webrtc:11140) : Fix those tests and remove this!
|
|
average.AddSample(time, value);
|
|
}
|
|
|
|
} // namespace rtc
|