Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(524)

Side by Side Diff: chrome/browser/metrics/random_selector_unittest.cc

Issue 1334943003: metrics: Add RandomSelector, a class that randomly selects items with odds (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add constructor for OddsAndValue Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
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 <cmath>
6 #include <map>
7 #include <string>
8
9 #include <base/strings/string_util.h>
Alexei Svitkine (slow) 2015/09/11 21:00:55 ""'s not <>'s.
dhsharp 2015/09/11 22:53:25 Done.
10 #include <gtest/gtest.h>
dhsharp 2015/09/11 22:53:25 For gtest/gtest.h, I looked around and saw a ~50/5
11
12 #include "chrome/browser/metrics/random_selector.h"
Alexei Svitkine (slow) 2015/09/11 21:00:54 Should be first include.
dhsharp 2015/09/11 22:53:25 Done.
13
14 using metrics::RandomSelector;
Alexei Svitkine (slow) 2015/09/11 21:00:55 Put this code in the metrics namespace instead.
dhsharp 2015/09/11 22:53:25 Done.
15
16 namespace {
17
18 // A small floating point number used to verify that the expected odds are equal
19 // to the odds set.
20 const double kEpsilon = 0.01;
21
22 // A class that overrides RandDoubleUpTo() to not be random. The number
23 // generator will emulate a uniform distribution of numbers between 0.0 and
24 // |max| when called with the same |max| parameter and a whole multiple of
25 // |random_period| times. This allows better testing of the RandomSelector
26 // class.
27 class RandomSelectorWithCustomRNG : public RandomSelector {
28 public:
29 explicit RandomSelectorWithCustomRNG(unsigned int random_period)
30 : random_period_(random_period), current_index_(0) {}
31
32 private:
33 // This function returns floats between 0.0 and |max| in an increasing
34 // fashion at regular intervals.
35 double RandDoubleUpTo(double max) override {
36 current_index_ = (current_index_ + 1) % random_period_;
37 return max * current_index_ / random_period_;
38 }
39
40 // Period (number of calls) over which the fake RNG repeats.
41 const unsigned int random_period_;
42
43 // Stores the current position we are at in the interval between 0.0 and
44 // |max|. See the function RandDoubleUpTo for details on how this is used.
45 int current_index_;
46 };
Alexei Svitkine (slow) 2015/09/11 21:00:55 DISALLOW_COPY_AND_ASSIGN()
dhsharp 2015/09/11 22:53:25 Done.
47
48 // Use the random_selector to generate some values. The number of values to
49 // generate is |iterations|.
50 void GenerateResults(size_t iterations,
51 RandomSelector* random_selector,
52 std::map<std::string, int>* results) {
53 for (size_t i = 0; i < iterations; ++i) {
54 const std::vector<std::string>& next_value = random_selector->GetNext();
55 std::string joined = base::JoinString(next_value, " ");
56 (*results)[joined]++;
57 }
58 }
59
60 // This function tests whether the results are close enough to the odds (within
61 // 1%).
62 void CheckResultsAgainstOdds(
63 const std::vector<RandomSelector::OddsAndValue>& odds,
64 const std::map<std::string, int>& results) {
65 EXPECT_EQ(odds.size(), results.size());
66
67 const double odds_sum = RandomSelector::SumOdds(odds);
68 int results_sum = 0;
69 for (const auto& item : results) {
70 results_sum += item.second;
71 }
72
73 for (const auto& odd : odds) {
74 const auto result = results.find(base::JoinString(odd.value, " "));
75 EXPECT_NE(result, results.end());
76 const double results_ratio = 1.0*result->second / results_sum;
77 const double odds_ratio = odd.weight / odds_sum;
78 const double abs_diff = std::abs(results_ratio - odds_ratio);
79 EXPECT_LT(abs_diff, kEpsilon);
80 }
81 }
82
83 const char* kCmdA[] = {"a", "1"};
84 const char* kCmdB[] = {"b", "--help"};
85 const char* kCmdC[] = {"c", "bar"};
86
87 } // namespace
88
89 TEST(RandomSelector, SimpleAccessors) {
90 using OddsAndValue = RandomSelector::OddsAndValue;
91 std::vector<OddsAndValue> odds;
92 odds.push_back(OddsAndValue(1, kCmdA));
93 odds.push_back(OddsAndValue(3, kCmdB));
94 odds.push_back(OddsAndValue(107, kCmdC));
95 EXPECT_EQ(111.0L, RandomSelector::SumOdds(odds));
96 RandomSelector random_selector;
97 random_selector.SetOdds(odds);
98 EXPECT_EQ(3UL, random_selector.GetNumValues());
99 }
100
101 // Ensure RandomSelector is able to generate results from given odds.
102 TEST(RandomSelector, GenerateTest) {
103 using OddsAndValue = RandomSelector::OddsAndValue;
104 const int kLargeNumber = 2000;
105 std::vector<RandomSelector::OddsAndValue> odds;
106 odds.push_back(OddsAndValue(1, kCmdA));
107 odds.push_back(OddsAndValue(2, kCmdB));
108 odds.push_back(OddsAndValue(3, kCmdC));
109 RandomSelectorWithCustomRNG random_selector(kLargeNumber);
110 random_selector.SetOdds(odds);
111 // Generate a lot of values.
112 std::map<std::string, int> results;
113 GenerateResults(kLargeNumber, &random_selector, &results);
114 // Ensure the values and odds are related.
115 CheckResultsAgainstOdds(odds, results);
116 }
117
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698