tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

samples_stats_counter_unittest.cc (7714B)


      1 /*
      2 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "api/numerics/samples_stats_counter.h"
     12 
     13 #include <cmath>
     14 #include <random>
     15 #include <vector>
     16 
     17 #include "absl/algorithm/container.h"
     18 #include "api/units/timestamp.h"
     19 #include "test/gtest.h"
     20 
     21 namespace webrtc {
     22 namespace {
     23 
     24 constexpr Timestamp kTimestamp = Timestamp::Seconds(1);
     25 
     26 SamplesStatsCounter CreateStatsFilledWithIntsFrom1ToN(int n) {
     27  std::vector<double> data;
     28  for (int i = 1; i <= n; i++) {
     29    data.push_back(i);
     30  }
     31  absl::c_shuffle(data, std::mt19937(std::random_device()()));
     32 
     33  SamplesStatsCounter stats;
     34  for (double v : data) {
     35    stats.AddSample({.value = v, .time = kTimestamp});
     36  }
     37  return stats;
     38 }
     39 
     40 // Add n samples drawn from uniform distribution in [a;b].
     41 SamplesStatsCounter CreateStatsFromUniformDistribution(int n,
     42                                                       double a,
     43                                                       double b) {
     44  std::mt19937 gen{std::random_device()()};
     45  std::uniform_real_distribution<> dis(a, b);
     46 
     47  SamplesStatsCounter stats;
     48  for (int i = 1; i <= n; i++) {
     49    stats.AddSample({.value = dis(gen), .time = kTimestamp});
     50  }
     51  return stats;
     52 }
     53 
     54 class SamplesStatsCounterTest : public ::testing::TestWithParam<int> {};
     55 
     56 constexpr int SIZE_FOR_MERGE = 10;
     57 
     58 }  // namespace
     59 
     60 TEST(SamplesStatsCounterTest, FullSimpleTest) {
     61  SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(100);
     62 
     63  EXPECT_TRUE(!stats.IsEmpty());
     64  EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0);
     65  EXPECT_DOUBLE_EQ(stats.GetMax(), 100.0);
     66  EXPECT_DOUBLE_EQ(stats.GetSum(), 5050.0);
     67  EXPECT_NEAR(stats.GetAverage(), 50.5, 1e-6);
     68  for (int i = 1; i <= 100; i++) {
     69    double p = i / 100.0;
     70    EXPECT_GE(stats.GetPercentile(p), i);
     71    EXPECT_LT(stats.GetPercentile(p), i + 1);
     72  }
     73 }
     74 
     75 TEST(SamplesStatsCounterTest, VarianceAndDeviation) {
     76  SamplesStatsCounter stats;
     77  stats.AddSample({.value = 2, .time = kTimestamp});
     78  stats.AddSample({.value = 2, .time = kTimestamp});
     79  stats.AddSample({.value = -1, .time = kTimestamp});
     80  stats.AddSample({.value = 5, .time = kTimestamp});
     81 
     82  EXPECT_DOUBLE_EQ(stats.GetAverage(), 2.0);
     83  EXPECT_DOUBLE_EQ(stats.GetVariance(), 4.5);
     84  EXPECT_DOUBLE_EQ(stats.GetStandardDeviation(), sqrt(4.5));
     85 }
     86 
     87 TEST(SamplesStatsCounterTest, FractionPercentile) {
     88  SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(5);
     89 
     90  EXPECT_DOUBLE_EQ(stats.GetPercentile(0.5), 3);
     91 }
     92 
     93 TEST(SamplesStatsCounterTest, TestBorderValues) {
     94  SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(5);
     95 
     96  EXPECT_GE(stats.GetPercentile(0.01), 1);
     97  EXPECT_LT(stats.GetPercentile(0.01), 2);
     98  EXPECT_DOUBLE_EQ(stats.GetPercentile(1.0), 5);
     99 }
    100 
    101 TEST(SamplesStatsCounterTest, VarianceFromUniformDistribution) {
    102  // Check variance converge to 1/12 for [0;1) uniform distribution.
    103  // Acts as a sanity check for NumericStabilityForVariance test.
    104  SamplesStatsCounter stats = CreateStatsFromUniformDistribution(1e6, 0, 1);
    105 
    106  EXPECT_NEAR(stats.GetVariance(), 1. / 12, 1e-3);
    107 }
    108 
    109 TEST(SamplesStatsCounterTest, NumericStabilityForVariance) {
    110  // Same test as VarianceFromUniformDistribution,
    111  // except the range is shifted to [1e9;1e9+1).
    112  // Variance should also converge to 1/12.
    113  // NB: Although we lose precision for the samples themselves, the fractional
    114  //     part still enjoys 22 bits of mantissa and errors should even out,
    115  //     so that couldn't explain a mismatch.
    116  SamplesStatsCounter stats =
    117      CreateStatsFromUniformDistribution(1e6, 1e9, 1e9 + 1);
    118 
    119  EXPECT_NEAR(stats.GetVariance(), 1. / 12, 1e-3);
    120 }
    121 
    122 TEST_P(SamplesStatsCounterTest, AddSamples) {
    123  double data[SIZE_FOR_MERGE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    124  // Split the data in different partitions.
    125  // We have 11 distinct tests:
    126  //   * Empty merged with full sequence.
    127  //   * 1 sample merged with 9 last.
    128  //   * 2 samples merged with 8 last.
    129  //   [...]
    130  //   * Full merged with empty sequence.
    131  // All must lead to the same result.
    132  SamplesStatsCounter stats0, stats1;
    133  for (int i = 0; i < GetParam(); ++i) {
    134    stats0.AddSample({.value = data[i], .time = kTimestamp});
    135  }
    136  for (int i = GetParam(); i < SIZE_FOR_MERGE; ++i) {
    137    stats1.AddSample({.value = data[i], .time = kTimestamp});
    138  }
    139  stats0.AddSamples(stats1);
    140 
    141  EXPECT_EQ(stats0.GetMin(), 0);
    142  EXPECT_EQ(stats0.GetMax(), 9);
    143  EXPECT_DOUBLE_EQ(stats0.GetAverage(), 4.5);
    144  EXPECT_DOUBLE_EQ(stats0.GetVariance(), 8.25);
    145  EXPECT_DOUBLE_EQ(stats0.GetStandardDeviation(), sqrt(8.25));
    146  EXPECT_DOUBLE_EQ(stats0.GetPercentile(0.1), 0.9);
    147  EXPECT_DOUBLE_EQ(stats0.GetPercentile(0.5), 4.5);
    148  EXPECT_DOUBLE_EQ(stats0.GetPercentile(0.9), 8.1);
    149 }
    150 
    151 TEST(SamplesStatsCounterTest, MultiplyRight) {
    152  SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(10);
    153 
    154  EXPECT_TRUE(!stats.IsEmpty());
    155  EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0);
    156  EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0);
    157  EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5);
    158 
    159  SamplesStatsCounter multiplied_stats = stats * 10;
    160  EXPECT_TRUE(!multiplied_stats.IsEmpty());
    161  EXPECT_DOUBLE_EQ(multiplied_stats.GetMin(), 10.0);
    162  EXPECT_DOUBLE_EQ(multiplied_stats.GetMax(), 100.0);
    163  EXPECT_DOUBLE_EQ(multiplied_stats.GetAverage(), 55.0);
    164  EXPECT_EQ(multiplied_stats.GetSamples().size(), stats.GetSamples().size());
    165 
    166  // Check that origin stats were not modified.
    167  EXPECT_TRUE(!stats.IsEmpty());
    168  EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0);
    169  EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0);
    170  EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5);
    171 }
    172 
    173 TEST(SamplesStatsCounterTest, MultiplyLeft) {
    174  SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(10);
    175 
    176  EXPECT_TRUE(!stats.IsEmpty());
    177  EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0);
    178  EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0);
    179  EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5);
    180 
    181  SamplesStatsCounter multiplied_stats = 10 * stats;
    182  EXPECT_TRUE(!multiplied_stats.IsEmpty());
    183  EXPECT_DOUBLE_EQ(multiplied_stats.GetMin(), 10.0);
    184  EXPECT_DOUBLE_EQ(multiplied_stats.GetMax(), 100.0);
    185  EXPECT_DOUBLE_EQ(multiplied_stats.GetAverage(), 55.0);
    186  EXPECT_EQ(multiplied_stats.GetSamples().size(), stats.GetSamples().size());
    187 
    188  // Check that origin stats were not modified.
    189  EXPECT_TRUE(!stats.IsEmpty());
    190  EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0);
    191  EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0);
    192  EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5);
    193 }
    194 
    195 TEST(SamplesStatsCounterTest, Divide) {
    196  SamplesStatsCounter stats;
    197  for (int i = 1; i <= 10; i++) {
    198    stats.AddSample({.value = i * 10., .time = kTimestamp});
    199  }
    200 
    201  EXPECT_TRUE(!stats.IsEmpty());
    202  EXPECT_DOUBLE_EQ(stats.GetMin(), 10.0);
    203  EXPECT_DOUBLE_EQ(stats.GetMax(), 100.0);
    204  EXPECT_DOUBLE_EQ(stats.GetAverage(), 55.0);
    205 
    206  SamplesStatsCounter divided_stats = stats / 10;
    207  EXPECT_TRUE(!divided_stats.IsEmpty());
    208  EXPECT_DOUBLE_EQ(divided_stats.GetMin(), 1.0);
    209  EXPECT_DOUBLE_EQ(divided_stats.GetMax(), 10.0);
    210  EXPECT_DOUBLE_EQ(divided_stats.GetAverage(), 5.5);
    211  EXPECT_EQ(divided_stats.GetSamples().size(), stats.GetSamples().size());
    212 
    213  // Check that origin stats were not modified.
    214  EXPECT_TRUE(!stats.IsEmpty());
    215  EXPECT_DOUBLE_EQ(stats.GetMin(), 10.0);
    216  EXPECT_DOUBLE_EQ(stats.GetMax(), 100.0);
    217  EXPECT_DOUBLE_EQ(stats.GetAverage(), 55.0);
    218 }
    219 
    220 INSTANTIATE_TEST_SUITE_P(SamplesStatsCounterTests,
    221                         SamplesStatsCounterTest,
    222                         ::testing::Range(0, SIZE_FOR_MERGE + 1));
    223 
    224 }  // namespace webrtc