Thanks to visit codestin.com
Credit goes to chromium.googlesource.com

blob: 36532b8ad46f715cb607260d122fd007db144a20 [file] [log] [blame]
Ilya Nikolaevskiy07923942023-09-19 10:05:041// Copyright 2023 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/moving_window.h"
6
Arthur Sonzogni0844a992024-12-12 11:36:207#include <array>
8
Ilya Nikolaevskiye846edb12023-09-25 10:45:029#include "base/time/time.h"
Ilya Nikolaevskiy07923942023-09-19 10:05:0410#include "testing/gtest/include/gtest/gtest.h"
11
12namespace base {
13
14namespace {
15
Arthur Sonzogni0844a992024-12-12 11:36:2016constexpr auto kTestValues = std::to_array<int>({
Ilya Nikolaevskiy07923942023-09-19 10:05:0417 33, 1, 2, 7, 5, 2, 4, 45, 1000, 1, 100, 2, 200, 2, 2, 2, 300, 4, 1,
18 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1,
Arthur Sonzogni0844a992024-12-12 11:36:2019 2, 1, 4, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, 16, 1, 2, 1,
20});
Ilya Nikolaevskiy07923942023-09-19 10:05:0421
22} // namespace
23
24class MovingMaxTest : public testing::TestWithParam<unsigned int> {};
25
26INSTANTIATE_TEST_SUITE_P(All,
27 MovingMaxTest,
28 testing::ValuesIn({1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u,
29 10u, 17u, 20u, 100u}));
30
31TEST_P(MovingMaxTest, BlanketTest) {
32 const size_t window_size = GetParam();
33 MovingMax<int> window(window_size);
34 for (size_t i = 0; i < std::size(kTestValues); ++i) {
35 window.AddSample(kTestValues[i]);
36 int slow_max = kTestValues[i];
37 for (size_t j = 1; j < window_size && j <= i; ++j) {
38 slow_max = std::max(slow_max, kTestValues[i - j]);
39 }
40 EXPECT_EQ(window.Max(), slow_max);
41 }
42}
43
44TEST(MovingMax, SingleElementWindow) {
45 MovingMax<int> window(1u);
46 window.AddSample(100);
47 EXPECT_EQ(window.Max(), 100);
48 window.AddSample(1000);
49 EXPECT_EQ(window.Max(), 1000);
50 window.AddSample(1);
51 EXPECT_EQ(window.Max(), 1);
52 window.AddSample(3);
53 EXPECT_EQ(window.Max(), 3);
54 window.AddSample(4);
55 EXPECT_EQ(window.Max(), 4);
56}
57
58TEST(MovingMax, VeryLargeWindow) {
59 MovingMax<int> window(100u);
60 window.AddSample(100);
61 EXPECT_EQ(window.Max(), 100);
62 window.AddSample(1000);
63 EXPECT_EQ(window.Max(), 1000);
64 window.AddSample(1);
65 EXPECT_EQ(window.Max(), 1000);
66 window.AddSample(3);
67 EXPECT_EQ(window.Max(), 1000);
68 window.AddSample(4);
69 EXPECT_EQ(window.Max(), 1000);
70}
71
72TEST(MovingMax, Counts) {
73 MovingMax<int> window(3u);
74 EXPECT_EQ(window.Count(), 0u);
75 window.AddSample(100);
76 EXPECT_EQ(window.Count(), 1u);
77 window.AddSample(1000);
78 EXPECT_EQ(window.Count(), 2u);
79 window.AddSample(1);
80 EXPECT_EQ(window.Count(), 3u);
81 window.AddSample(3);
82 EXPECT_EQ(window.Count(), 4u);
83 window.AddSample(4);
84 EXPECT_EQ(window.Count(), 5u);
85}
86
Ilya Nikolaevskiye846edb12023-09-25 10:45:0287TEST(MovingAverage, Unrounded) {
88 MovingAverage<int, int64_t> window(4u);
Ilya Nikolaevskiy07923942023-09-19 10:05:0489 window.AddSample(1);
90 EXPECT_EQ(window.Mean<double>(), 1.0);
91 window.AddSample(2);
92 EXPECT_EQ(window.Mean<double>(), 1.5);
93 window.AddSample(3);
94 EXPECT_EQ(window.Mean<double>(), 2.0);
95 window.AddSample(4);
96 EXPECT_EQ(window.Mean<double>(), 2.5);
97 window.AddSample(101);
98 EXPECT_EQ(window.Mean<double>(), 27.5);
99}
100
101class MovingMinTest : public testing::TestWithParam<unsigned int> {};
102
103INSTANTIATE_TEST_SUITE_P(All,
104 MovingMinTest,
105 testing::ValuesIn({1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u,
106 10u, 17u, 20u, 100u}));
107
108TEST_P(MovingMinTest, BlanketTest) {
109 const size_t window_size = GetParam();
110 MovingMin<int> window(window_size);
111 for (int repeats = 0; repeats < 2; ++repeats) {
112 for (size_t i = 0; i < std::size(kTestValues); ++i) {
113 window.AddSample(kTestValues[i]);
114 int slow_min = kTestValues[i];
115 for (size_t j = 1; j < window_size && j <= i; ++j) {
116 slow_min = std::min(slow_min, kTestValues[i - j]);
117 }
118 EXPECT_EQ(window.Min(), slow_min);
119 }
120 window.Reset();
121 }
122}
123
Ilya Nikolaevskiye846edb12023-09-25 10:45:02124class MovingAverageTest : public testing::TestWithParam<unsigned int> {};
Ilya Nikolaevskiy07923942023-09-19 10:05:04125
126INSTANTIATE_TEST_SUITE_P(All,
Ilya Nikolaevskiye846edb12023-09-25 10:45:02127 MovingAverageTest,
Ilya Nikolaevskiy07923942023-09-19 10:05:04128 testing::ValuesIn({1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u,
129 10u, 17u, 20u, 100u}));
130
Ilya Nikolaevskiye846edb12023-09-25 10:45:02131TEST_P(MovingAverageTest, BlanketTest) {
Ilya Nikolaevskiy07923942023-09-19 10:05:04132 const size_t window_size = GetParam();
Ilya Nikolaevskiye846edb12023-09-25 10:45:02133 MovingAverage<int, int64_t> window(window_size);
Ilya Nikolaevskiy07923942023-09-19 10:05:04134 for (int repeats = 0; repeats < 2; ++repeats) {
135 for (size_t i = 0; i < std::size(kTestValues); ++i) {
136 window.AddSample(kTestValues[i]);
137 int slow_mean = 0;
138 for (size_t j = 0; j < window_size && j <= i; ++j) {
139 slow_mean += kTestValues[i - j];
140 }
141 slow_mean /= std::min(window_size, i + 1);
142 EXPECT_EQ(window.Mean(), slow_mean);
143 }
144 window.Reset();
145 }
146}
147
Ilya Nikolaevskiye846edb12023-09-25 10:45:02148class MovingDeviationTest : public testing::TestWithParam<unsigned int> {};
Ilya Nikolaevskiy07923942023-09-19 10:05:04149
150INSTANTIATE_TEST_SUITE_P(All,
Ilya Nikolaevskiye846edb12023-09-25 10:45:02151 MovingDeviationTest,
Ilya Nikolaevskiy07923942023-09-19 10:05:04152 testing::ValuesIn({1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u,
153 10u, 17u, 20u, 100u}));
154
Ilya Nikolaevskiye846edb12023-09-25 10:45:02155TEST_P(MovingDeviationTest, BlanketTest) {
Ilya Nikolaevskiy07923942023-09-19 10:05:04156 const size_t window_size = GetParam();
Ilya Nikolaevskiye846edb12023-09-25 10:45:02157 MovingAverageDeviation<double> window(window_size);
Ilya Nikolaevskiy07923942023-09-19 10:05:04158 for (int repeats = 0; repeats < 2; ++repeats) {
159 for (size_t i = 0; i < std::size(kTestValues); ++i) {
160 window.AddSample(kTestValues[i]);
Ilya Nikolaevskiye846edb12023-09-25 10:45:02161 double slow_deviation = 0;
Ilya Nikolaevskiy07923942023-09-19 10:05:04162 double mean = window.Mean();
163 for (size_t j = 0; j < window_size && j <= i; ++j) {
Ilya Nikolaevskiye846edb12023-09-25 10:45:02164 slow_deviation +=
Ilya Nikolaevskiy07923942023-09-19 10:05:04165 (kTestValues[i - j] - mean) * (kTestValues[i - j] - mean);
166 }
Ilya Nikolaevskiye846edb12023-09-25 10:45:02167 slow_deviation /= std::min(window_size, i + 1);
168 slow_deviation = sqrt(slow_deviation);
Ilya Nikolaevskiy07923942023-09-19 10:05:04169 double fast_deviation = window.Deviation();
Ilya Nikolaevskiy07923942023-09-19 10:05:04170 EXPECT_TRUE(std::abs(fast_deviation - slow_deviation) < 1e-9);
171 }
172 window.Reset();
173 }
174}
175
176TEST(MovingWindowTest, Iteration) {
177 const size_t kWindowSize = 10;
178 MovingWindow<int, base::MovingWindowFeatures::Iteration> window(kWindowSize);
179 for (int repeats = 0; repeats < 2; ++repeats) {
180 for (size_t i = 0; i < std::size(kTestValues); ++i) {
181 window.AddSample(kTestValues[i]);
182 size_t j = 0;
183 const size_t in_window = std::min(i + 1, kWindowSize);
184 for (int value : window) {
185 ASSERT_LT(j, in_window);
186 EXPECT_EQ(value, kTestValues[i + j + 1 - in_window]);
187 ++j;
188 }
189 EXPECT_EQ(j, in_window);
190 }
191 window.Reset();
192 }
193}
194
Ilya Nikolaevskiye846edb12023-09-25 10:45:02195TEST(MovingMeanDeviation, WorksWithTimeDelta) {
196 MovingAverageDeviation<base::TimeDelta> window(2);
197 window.AddSample(base::Milliseconds(400));
198 window.AddSample(base::Milliseconds(200));
199 EXPECT_EQ(window.Mean(), base::Milliseconds(300));
200 EXPECT_EQ(window.Deviation(), base::Milliseconds(100));
201 window.AddSample(base::Seconds(40));
202 window.AddSample(base::Seconds(20));
203 EXPECT_EQ(window.Mean(), base::Seconds(30));
204 EXPECT_EQ(window.Deviation(), base::Seconds(10));
205}
206
Ilya Nikolaevskiy07923942023-09-19 10:05:04207} // namespace base