1/*
2 * Copyright 2018-present Facebook, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <folly/stats/QuantileEstimator-defs.h>
18
19#include <folly/portability/GTest.h>
20
21using namespace folly;
22
23struct MockClock {
24 public:
25 using duration = std::chrono::steady_clock::duration;
26 using time_point = std::chrono::steady_clock::time_point;
27 static constexpr auto is_steady = true;
28
29 static time_point now() {
30 return Now;
31 }
32
33 static time_point Now;
34};
35
36MockClock::time_point MockClock::Now = MockClock::time_point{};
37
38TEST(SimpleQuantileEstimatorTest, EstimateQuantiles) {
39 SimpleQuantileEstimator<MockClock> estimator;
40 for (size_t i = 1; i <= 100; ++i) {
41 estimator.addValue(i);
42 }
43
44 MockClock::Now += std::chrono::seconds{1};
45
46 auto estimates = estimator.estimateQuantiles(
47 std::array<double, 5>{{.001, .01, .5, .99, .999}});
48
49 EXPECT_EQ(5050, estimates.sum);
50 EXPECT_EQ(100, estimates.count);
51
52 EXPECT_EQ(0.001, estimates.quantiles[0].first);
53 EXPECT_EQ(0.01, estimates.quantiles[1].first);
54 EXPECT_EQ(0.5, estimates.quantiles[2].first);
55 EXPECT_EQ(0.99, estimates.quantiles[3].first);
56 EXPECT_EQ(0.999, estimates.quantiles[4].first);
57
58 EXPECT_EQ(1, estimates.quantiles[0].second);
59 EXPECT_EQ(2.0 - 0.5, estimates.quantiles[1].second);
60 EXPECT_EQ(50.375, estimates.quantiles[2].second);
61 EXPECT_EQ(100.0 - 0.5, estimates.quantiles[3].second);
62 EXPECT_EQ(100, estimates.quantiles[4].second);
63}
64
65TEST(SlidingWindowQuantileEstimatorTest, EstimateQuantiles) {
66 SlidingWindowQuantileEstimator<MockClock> estimator(std::chrono::seconds{1});
67 for (size_t i = 1; i <= 100; ++i) {
68 estimator.addValue(i);
69 }
70
71 MockClock::Now += std::chrono::seconds{1};
72
73 auto estimates = estimator.estimateQuantiles(
74 std::array<double, 5>{{.001, .01, .5, .99, .999}});
75
76 EXPECT_EQ(5050, estimates.sum);
77 EXPECT_EQ(100, estimates.count);
78
79 EXPECT_EQ(0.001, estimates.quantiles[0].first);
80 EXPECT_EQ(0.01, estimates.quantiles[1].first);
81 EXPECT_EQ(0.5, estimates.quantiles[2].first);
82 EXPECT_EQ(0.99, estimates.quantiles[3].first);
83 EXPECT_EQ(0.999, estimates.quantiles[4].first);
84
85 EXPECT_EQ(1, estimates.quantiles[0].second);
86 EXPECT_EQ(2.0 - 0.5, estimates.quantiles[1].second);
87 EXPECT_EQ(50.375, estimates.quantiles[2].second);
88 EXPECT_EQ(100.0 - 0.5, estimates.quantiles[3].second);
89 EXPECT_EQ(100, estimates.quantiles[4].second);
90}
91