Revert 268246 "Revert 268232 "Refactor MetricsStateManager class..."

r268232 was erroneously blamed, so re-applying it.

> Revert 268232 "Refactor MetricsStateManager class out of Metrics..."
> 
> Failed 'sizes' check: chrome-si (static initializers) incremented.
> 
> > Refactor MetricsStateManager class out of MetricsService.
> > 
> > The new class is responsible for managing various MetricsService state prefs,
> > such as client id, low entropy source and the UMA opt-in state, as well as the
> > cloned install detector.
> > 
> > Also, moves IsMetricsReportingEnabled() from chrome_browser_main.cc to
> > the new class as well as changing a couple MetricsService browser tests
> > to instead be unit tests of the new class.
> > 
> > BUG=368413
> > 
> > Review URL: https://codereview.chromium.org/256143006
> 
> [email protected]
> 
> Review URL: https://codereview.chromium.org/268223002

[email protected]

Review URL: https://codereview.chromium.org/270013002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@268264 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/metrics/metrics_state_manager_unittest.cc b/chrome/browser/metrics/metrics_state_manager_unittest.cc
new file mode 100644
index 0000000..bad4b77
--- /dev/null
+++ b/chrome/browser/metrics/metrics_state_manager_unittest.cc
@@ -0,0 +1,160 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/metrics_state_manager.h"
+
+#include <ctype.h>
+#include <string>
+
+#include "base/command_line.h"
+#include "base/prefs/testing_pref_service.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/metrics/caching_permuted_entropy_provider.h"
+#include "chrome/common/pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace metrics {
+
+class MetricsStateManagerTest : public testing::Test {
+ public:
+  MetricsStateManagerTest() {
+    MetricsStateManager::RegisterPrefs(prefs_.registry());
+  }
+
+  scoped_ptr<MetricsStateManager> CreateStateManager() {
+    return MetricsStateManager::Create(&prefs_).Pass();
+  }
+
+ protected:
+  TestingPrefServiceSimple prefs_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MetricsStateManagerTest);
+};
+
+// Ensure the ClientId is formatted as expected.
+TEST_F(MetricsStateManagerTest, ClientIdCorrectlyFormatted) {
+  scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
+  state_manager->ForceClientIdCreation();
+
+  const std::string client_id = state_manager->client_id();
+  EXPECT_EQ(36U, client_id.length());
+
+  for (size_t i = 0; i < client_id.length(); ++i) {
+    char current = client_id[i];
+    if (i == 8 || i == 13 || i == 18 || i == 23)
+      EXPECT_EQ('-', current);
+    else
+      EXPECT_TRUE(isxdigit(current));
+  }
+}
+
+TEST_F(MetricsStateManagerTest, EntropySourceUsed_Low) {
+  scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
+  state_manager->CreateEntropyProvider();
+  EXPECT_EQ(MetricsStateManager::ENTROPY_SOURCE_LOW,
+            state_manager->entropy_source_returned());
+}
+
+TEST_F(MetricsStateManagerTest, EntropySourceUsed_High) {
+  CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableMetricsReportingForTesting);
+
+  scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
+  state_manager->CreateEntropyProvider();
+  EXPECT_EQ(MetricsStateManager::ENTROPY_SOURCE_HIGH,
+            state_manager->entropy_source_returned());
+}
+
+TEST_F(MetricsStateManagerTest, LowEntropySource0NotReset) {
+  scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
+
+  // Get the low entropy source once, to initialize it.
+  state_manager->GetLowEntropySource();
+
+  // Now, set it to 0 and ensure it doesn't get reset.
+  state_manager->low_entropy_source_ = 0;
+  EXPECT_EQ(0, state_manager->GetLowEntropySource());
+  // Call it another time, just to make sure.
+  EXPECT_EQ(0, state_manager->GetLowEntropySource());
+}
+
+TEST_F(MetricsStateManagerTest,
+       PermutedEntropyCacheClearedWhenLowEntropyReset) {
+  const PrefService::Preference* low_entropy_pref =
+      prefs_.FindPreference(prefs::kMetricsLowEntropySource);
+  const char* kCachePrefName = prefs::kMetricsPermutedEntropyCache;
+  int low_entropy_value = -1;
+
+  // First, generate an initial low entropy source value.
+  {
+    EXPECT_TRUE(low_entropy_pref->IsDefaultValue());
+
+    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
+    state_manager->GetLowEntropySource();
+
+    EXPECT_FALSE(low_entropy_pref->IsDefaultValue());
+    EXPECT_TRUE(low_entropy_pref->GetValue()->GetAsInteger(&low_entropy_value));
+  }
+
+  // Now, set a dummy value in the permuted entropy cache pref and verify that
+  // another call to GetLowEntropySource() doesn't clobber it when
+  // --reset-variation-state wasn't specified.
+  {
+    prefs_.SetString(kCachePrefName, "test");
+
+    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
+    state_manager->GetLowEntropySource();
+
+    EXPECT_EQ("test", prefs_.GetString(kCachePrefName));
+    EXPECT_EQ(low_entropy_value,
+              prefs_.GetInteger(prefs::kMetricsLowEntropySource));
+  }
+
+  // Verify that the cache does get reset if --reset-variations-state is passed.
+  {
+    CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kResetVariationState);
+
+    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
+    state_manager->GetLowEntropySource();
+
+    EXPECT_TRUE(prefs_.GetString(kCachePrefName).empty());
+  }
+}
+
+// Check that setting the kMetricsResetIds pref to true causes the client id to
+// be reset. We do not check that the low entropy source is reset because we
+// cannot ensure that metrics state manager won't generate the same id again.
+TEST_F(MetricsStateManagerTest, ResetMetricsIDs) {
+  // Set an initial client id in prefs. It should not be possible for the
+  // metrics state manager to generate this id randomly.
+  const std::string kInitialClientId = "initial client id";
+  prefs_.SetString(prefs::kMetricsClientID, kInitialClientId);
+
+  // Make sure the initial client id isn't reset by the metrics state manager.
+  {
+    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
+    state_manager->ForceClientIdCreation();
+    EXPECT_EQ(kInitialClientId, state_manager->client_id());
+  }
+
+  // Set the reset pref to cause the IDs to be reset.
+  prefs_.SetBoolean(prefs::kMetricsResetIds, true);
+
+  // Cause the actual reset to happen.
+  {
+    scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
+    state_manager->ForceClientIdCreation();
+    EXPECT_NE(kInitialClientId, state_manager->client_id());
+
+    state_manager->GetLowEntropySource();
+
+    EXPECT_FALSE(prefs_.GetBoolean(prefs::kMetricsResetIds));
+  }
+
+  EXPECT_NE(kInitialClientId, prefs_.GetString(prefs::kMetricsClientID));
+}
+
+}  // namespace metrics