1// Copyright 2014 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 "components/metrics/metrics_state_manager.h"
6
7#include <ctype.h>
8#include <string>
9
10#include "base/bind.h"
11#include "base/command_line.h"
12#include "base/prefs/testing_pref_service.h"
13#include "components/metrics/metrics_pref_names.h"
14#include "components/metrics/metrics_switches.h"
15#include "components/variations/caching_permuted_entropy_provider.h"
16#include "components/variations/pref_names.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19namespace metrics {
20
21class MetricsStateManagerTest : public testing::Test {
22 public:
23  MetricsStateManagerTest() : is_metrics_reporting_enabled_(false) {
24    MetricsStateManager::RegisterPrefs(prefs_.registry());
25  }
26
27  scoped_ptr<MetricsStateManager> CreateStateManager() {
28    return MetricsStateManager::Create(
29        &prefs_,
30        base::Bind(&MetricsStateManagerTest::is_metrics_reporting_enabled,
31                   base::Unretained(this))).Pass();
32  }
33
34  // Sets metrics reporting as enabled for testing.
35  void EnableMetricsReporting() {
36    is_metrics_reporting_enabled_ = true;
37  }
38
39 protected:
40  TestingPrefServiceSimple prefs_;
41
42 private:
43  bool is_metrics_reporting_enabled() const {
44    return is_metrics_reporting_enabled_;
45  }
46
47  bool is_metrics_reporting_enabled_;
48
49  DISALLOW_COPY_AND_ASSIGN(MetricsStateManagerTest);
50};
51
52// Ensure the ClientId is formatted as expected.
53TEST_F(MetricsStateManagerTest, ClientIdCorrectlyFormatted) {
54  scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
55  state_manager->ForceClientIdCreation();
56
57  const std::string client_id = state_manager->client_id();
58  EXPECT_EQ(36U, client_id.length());
59
60  for (size_t i = 0; i < client_id.length(); ++i) {
61    char current = client_id[i];
62    if (i == 8 || i == 13 || i == 18 || i == 23)
63      EXPECT_EQ('-', current);
64    else
65      EXPECT_TRUE(isxdigit(current));
66  }
67}
68
69TEST_F(MetricsStateManagerTest, EntropySourceUsed_Low) {
70  scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
71  state_manager->CreateEntropyProvider();
72  EXPECT_EQ(MetricsStateManager::ENTROPY_SOURCE_LOW,
73            state_manager->entropy_source_returned());
74}
75
76TEST_F(MetricsStateManagerTest, EntropySourceUsed_High) {
77  EnableMetricsReporting();
78  scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
79  state_manager->CreateEntropyProvider();
80  EXPECT_EQ(MetricsStateManager::ENTROPY_SOURCE_HIGH,
81            state_manager->entropy_source_returned());
82}
83
84TEST_F(MetricsStateManagerTest, LowEntropySource0NotReset) {
85  scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
86
87  // Get the low entropy source once, to initialize it.
88  state_manager->GetLowEntropySource();
89
90  // Now, set it to 0 and ensure it doesn't get reset.
91  state_manager->low_entropy_source_ = 0;
92  EXPECT_EQ(0, state_manager->GetLowEntropySource());
93  // Call it another time, just to make sure.
94  EXPECT_EQ(0, state_manager->GetLowEntropySource());
95}
96
97TEST_F(MetricsStateManagerTest,
98       PermutedEntropyCacheClearedWhenLowEntropyReset) {
99  const PrefService::Preference* low_entropy_pref =
100      prefs_.FindPreference(prefs::kMetricsLowEntropySource);
101  const char* kCachePrefName = prefs::kVariationsPermutedEntropyCache;
102  int low_entropy_value = -1;
103
104  // First, generate an initial low entropy source value.
105  {
106    EXPECT_TRUE(low_entropy_pref->IsDefaultValue());
107
108    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
109    state_manager->GetLowEntropySource();
110
111    EXPECT_FALSE(low_entropy_pref->IsDefaultValue());
112    EXPECT_TRUE(low_entropy_pref->GetValue()->GetAsInteger(&low_entropy_value));
113  }
114
115  // Now, set a dummy value in the permuted entropy cache pref and verify that
116  // another call to GetLowEntropySource() doesn't clobber it when
117  // --reset-variation-state wasn't specified.
118  {
119    prefs_.SetString(kCachePrefName, "test");
120
121    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
122    state_manager->GetLowEntropySource();
123
124    EXPECT_EQ("test", prefs_.GetString(kCachePrefName));
125    EXPECT_EQ(low_entropy_value,
126              prefs_.GetInteger(prefs::kMetricsLowEntropySource));
127  }
128
129  // Verify that the cache does get reset if --reset-variations-state is passed.
130  {
131    CommandLine::ForCurrentProcess()->AppendSwitch(
132        switches::kResetVariationState);
133
134    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
135    state_manager->GetLowEntropySource();
136
137    EXPECT_TRUE(prefs_.GetString(kCachePrefName).empty());
138  }
139}
140
141// Check that setting the kMetricsResetIds pref to true causes the client id to
142// be reset. We do not check that the low entropy source is reset because we
143// cannot ensure that metrics state manager won't generate the same id again.
144TEST_F(MetricsStateManagerTest, ResetMetricsIDs) {
145  // Set an initial client id in prefs. It should not be possible for the
146  // metrics state manager to generate this id randomly.
147  const std::string kInitialClientId = "initial client id";
148  prefs_.SetString(prefs::kMetricsClientID, kInitialClientId);
149
150  // Make sure the initial client id isn't reset by the metrics state manager.
151  {
152    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
153    state_manager->ForceClientIdCreation();
154    EXPECT_EQ(kInitialClientId, state_manager->client_id());
155  }
156
157  // Set the reset pref to cause the IDs to be reset.
158  prefs_.SetBoolean(prefs::kMetricsResetIds, true);
159
160  // Cause the actual reset to happen.
161  {
162    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
163    state_manager->ForceClientIdCreation();
164    EXPECT_NE(kInitialClientId, state_manager->client_id());
165
166    state_manager->GetLowEntropySource();
167
168    EXPECT_FALSE(prefs_.GetBoolean(prefs::kMetricsResetIds));
169  }
170
171  EXPECT_NE(kInitialClientId, prefs_.GetString(prefs::kMetricsClientID));
172}
173
174}  // namespace metrics
175