root/chrome/browser/profile_resetter/automatic_profile_resetter_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetLoadedModuleNameDigests
  2. GetDefaultSearchProviderDetails
  3. IsDefaultSearchProviderManaged
  4. GetPrepopulatedSearchProvidersDetails
  5. ClosureInvoker
  6. ExpectCallsToDependenciesSetUpMethods
  7. ExpectCallsToGetterMethods
  8. ExpectCallToShowPrompt
  9. ExpectCallToTriggerReset
  10. emulated_default_search_provider_details
  11. emulated_search_providers_details
  12. emulated_loaded_module_digests
  13. set_emulated_is_default_search_provider_managed
  14. EmulateProfileResetCompleted
  15. ReadValue
  16. StoreValue
  17. AssignArgumentTo
  18. GetHash
  19. EncodeBool
  20. ConstructProgram
  21. ConstructProgramToExerciseCriteria
  22. ConstructProgramToCheckPreferences
  23. ConstructProgramToCheckSearchEngines
  24. ConstructProgramToCheckLoadedModuleDigests
  25. mock_delegate_
  26. SetUp
  27. SetTestingHashSeed
  28. SetTestingProgram
  29. AllowInjectingTestDataThroughVariationParams
  30. ExpectAllMementoValuesEqualTo
  31. UnleashResetterAndWait
  32. OrchestrateThroughEvaluationFlow
  33. VerifyExpectationsThenShutdownResetter
  34. profile
  35. local_state
  36. memento_in_prefs
  37. memento_in_local_state
  38. memento_in_file
  39. mock_delegate
  40. resetter
  41. TEST_F
  42. TEST_F
  43. TEST_F
  44. TEST_F
  45. TEST_F
  46. TEST_F
  47. TEST_F
  48. TEST_F
  49. TEST_F
  50. TEST_F
  51. TEST_F
  52. TEST_F
  53. TEST_F
  54. TEST_F
  55. TEST_F
  56. TEST_F
  57. TEST_F
  58. TEST_F
  59. TEST_F
  60. TEST_F
  61. TEST_F
  62. TEST_F
  63. TEST_F
  64. TEST_F
  65. TEST_F
  66. TEST_F
  67. TEST_F
  68. TEST_F
  69. TEST_F
  70. TEST_F
  71. TEST_F
  72. TEST_F
  73. TEST_F
  74. TEST_F
  75. TEST_F
  76. TEST_F
  77. TEST_F
  78. TEST_F
  79. TEST_F
  80. TEST_F

// Copyright 2013 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/profile_resetter/automatic_profile_resetter.h"

#include <string>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/metrics/field_trial.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/testing_pref_service.h"
#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/values.h"
#include "chrome/browser/profile_resetter/automatic_profile_resetter_delegate.h"
#include "chrome/browser/profile_resetter/automatic_profile_resetter_factory.h"
#include "chrome/browser/profile_resetter/automatic_profile_resetter_mementos.h"
#include "chrome/browser/profile_resetter/jtl_foundation.h"
#include "chrome/browser/profile_resetter/jtl_instructions.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_pref_service_syncable.h"
#include "chrome/test/base/testing_profile.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "components/variations/variations_associated_data.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::_;

namespace {

const char kAutomaticProfileResetStudyName[] = "AutomaticProfileReset";
const char kStudyDisabledGroupName[] = "Disabled";
const char kStudyDryRunGroupName[] = "DryRun";
const char kStudyEnabledGroupName[] = "Enabled";

const char kTestHashSeed[] = "testing-hash-seed";
const char kTestMementoValue[] = "01234567890123456789012345678901";
const char kTestInvalidMementoValue[] = "12345678901234567890123456789012";

const char kTestPreferencePath[] = "testing.preference";
const char kTestPreferenceValue[] = "testing-preference-value";

const char kSearchURLAttributeKey[] = "search_url";
const char kTestSearchURL[] = "http://example.com/search?q={searchTerms}";
const char kTestSearchURL2[] = "http://google.com/?q={searchTerms}";

const char kTestModuleDigest[] = "01234567890123456789012345678901";
const char kTestModuleDigest2[] = "12345678901234567890123456789012";

// Helpers ------------------------------------------------------------------

// A testing version of the AutomaticProfileResetter that differs from the real
// one only in that it has its statistics reporting mocked out for verification.
class AutomaticProfileResetterUnderTest : public AutomaticProfileResetter {
 public:
  explicit AutomaticProfileResetterUnderTest(Profile* profile)
      : AutomaticProfileResetter(profile) {}
  virtual ~AutomaticProfileResetterUnderTest() {}

  MOCK_METHOD2(ReportStatistics, void(uint32, uint32));
  MOCK_METHOD1(ReportPromptResult,
      void(AutomaticProfileResetter::PromptResult));

 private:
  DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterUnderTest);
};

class MockProfileResetterDelegate : public AutomaticProfileResetterDelegate {
 public:
  MockProfileResetterDelegate()
      : emulated_is_default_search_provider_managed_(false) {}
  virtual ~MockProfileResetterDelegate() {}

  MOCK_METHOD0(EnumerateLoadedModulesIfNeeded, void());
  MOCK_CONST_METHOD1(RequestCallbackWhenLoadedModulesAreEnumerated,
                     void(const base::Closure&));

  MOCK_METHOD0(LoadTemplateURLServiceIfNeeded, void());
  MOCK_CONST_METHOD1(RequestCallbackWhenTemplateURLServiceIsLoaded,
                     void(const base::Closure&));

  MOCK_METHOD0(FetchBrandcodedDefaultSettingsIfNeeded, void());
  MOCK_CONST_METHOD1(RequestCallbackWhenBrandcodedDefaultsAreFetched,
                     void(const base::Closure&));

  MOCK_CONST_METHOD0(OnGetLoadedModuleNameDigestsCalled, void());
  MOCK_CONST_METHOD0(OnGetDefaultSearchProviderDetailsCalled, void());
  MOCK_CONST_METHOD0(OnIsDefaultSearchProviderManagedCalled, void());
  MOCK_CONST_METHOD0(OnGetPrepopulatedSearchProvidersDetailsCalled, void());

  MOCK_METHOD0(TriggerPrompt, bool());
  MOCK_METHOD2(TriggerProfileSettingsReset, void(bool, const base::Closure&));
  MOCK_METHOD0(DismissPrompt, void());

  virtual scoped_ptr<base::ListValue>
      GetLoadedModuleNameDigests() const OVERRIDE {
    OnGetLoadedModuleNameDigestsCalled();
    return scoped_ptr<base::ListValue>(
        emulated_loaded_module_digests_.DeepCopy());
  }

  virtual scoped_ptr<base::DictionaryValue>
      GetDefaultSearchProviderDetails() const OVERRIDE {
    OnGetDefaultSearchProviderDetailsCalled();
    return scoped_ptr<base::DictionaryValue>(
        emulated_default_search_provider_details_.DeepCopy());
  }

  virtual bool IsDefaultSearchProviderManaged() const OVERRIDE {
    OnIsDefaultSearchProviderManagedCalled();
    return emulated_is_default_search_provider_managed_;
  }

  virtual scoped_ptr<base::ListValue>
      GetPrepopulatedSearchProvidersDetails() const OVERRIDE {
    OnGetPrepopulatedSearchProvidersDetailsCalled();
    return scoped_ptr<base::ListValue>(
        emulated_search_providers_details_.DeepCopy());
  }

  static void ClosureInvoker(const base::Closure& closure) { closure.Run(); }

  void ExpectCallsToDependenciesSetUpMethods() {
    EXPECT_CALL(*this, EnumerateLoadedModulesIfNeeded());
    EXPECT_CALL(*this, LoadTemplateURLServiceIfNeeded());
    EXPECT_CALL(*this, RequestCallbackWhenLoadedModulesAreEnumerated(_))
        .WillOnce(testing::Invoke(ClosureInvoker));
    EXPECT_CALL(*this, RequestCallbackWhenTemplateURLServiceIsLoaded(_))
        .WillOnce(testing::Invoke(ClosureInvoker));
  }

  void ExpectCallsToGetterMethods() {
    EXPECT_CALL(*this, OnGetLoadedModuleNameDigestsCalled());
    EXPECT_CALL(*this, OnGetDefaultSearchProviderDetailsCalled());
    EXPECT_CALL(*this, OnIsDefaultSearchProviderManagedCalled());
    EXPECT_CALL(*this, OnGetPrepopulatedSearchProvidersDetailsCalled());
  }

  void ExpectCallToShowPrompt() {
    EXPECT_CALL(*this, TriggerPrompt()).WillOnce(testing::Return(true));
    EXPECT_CALL(*this, FetchBrandcodedDefaultSettingsIfNeeded());
  }

  void ExpectCallToTriggerReset(bool send_feedback) {
    EXPECT_CALL(*this, TriggerProfileSettingsReset(send_feedback, _))
        .WillOnce(testing::SaveArg<1>(&reset_completion_));
  }

  base::DictionaryValue& emulated_default_search_provider_details() {
    return emulated_default_search_provider_details_;
  }

  base::ListValue& emulated_search_providers_details() {
    return emulated_search_providers_details_;
  }

  base::ListValue& emulated_loaded_module_digests() {
    return emulated_loaded_module_digests_;
  }

  void set_emulated_is_default_search_provider_managed(bool value) {
    emulated_is_default_search_provider_managed_ = value;
  }

  void EmulateProfileResetCompleted() {
    reset_completion_.Run();
  }

 private:
  base::DictionaryValue emulated_default_search_provider_details_;
  base::ListValue emulated_search_providers_details_;
  base::ListValue emulated_loaded_module_digests_;
  bool emulated_is_default_search_provider_managed_;
  base::Closure reset_completion_;

  DISALLOW_COPY_AND_ASSIGN(MockProfileResetterDelegate);
};

class FileHostedPromptMementoSynchronous : protected FileHostedPromptMemento {
 public:
  explicit FileHostedPromptMementoSynchronous(Profile* profile)
      : FileHostedPromptMemento(profile) {}

  std::string ReadValue() const {
    std::string result;
    FileHostedPromptMemento::ReadValue(base::Bind(&AssignArgumentTo, &result));
    base::RunLoop().RunUntilIdle();
    return result;
  }

  void StoreValue(const std::string& value) {
    FileHostedPromptMemento::StoreValue(value);
    base::RunLoop().RunUntilIdle();
  }

 private:
  static void AssignArgumentTo(std::string* target, const std::string& value) {
    *target = value;
  }

  DISALLOW_COPY_AND_ASSIGN(FileHostedPromptMementoSynchronous);
};

std::string GetHash(const std::string& input) {
  return jtl_foundation::Hasher(kTestHashSeed).GetHash(input);
}

// Encodes a Boolean argument value into JTL bytecode.
std::string EncodeBool(bool value) { return value ? VALUE_TRUE : VALUE_FALSE; }

// Constructs a simple evaluation program to test that basic input/output works
// well. It will emulate a scenario in which the reset criteria are satisfied as
// prescribed by |emulate_satisfied_criterion_{1|2}|, and the reset is triggered
// when either of them is true. The bits in the combined status mask will be set
// according to whether or not the memento values received in the input were as
// expected.
//
// More specifically, the output of the program will be as follows:
// {
//   "satisfied_criteria_mask_bit1": emulate_satisfied_criterion_1,
//   "satisfied_criteria_mask_bit2": emulate_satisfied_criterion_2,
//   "combined_status_mask_bit1":
//      (emulate_satisfied_criterion_1 || emulate_satisfied_criterion_2),
//   "combined_status_mask_bit2":
//      (input["memento_value_in_prefs"] == kTestMementoValue),
//   "combined_status_mask_bit3":
//      (input["memento_value_in_local_state"] == kTestMementoValue),
//   "combined_status_mask_bit4":
//      (input["memento_value_in_file"] == kTestMementoValue),
//   "should_prompt":
//      (emulate_satisfied_criterion_1 || emulate_satisfied_criterion_2),
//   "had_prompted_already": <OR-combination of above three>,
//   "memento_value_in_prefs": kTestMementoValue,
//   "memento_value_in_local_state": kTestMementoValue,
//   "memento_value_in_file": kTestMementoValue
// }
std::string ConstructProgram(bool emulate_satisfied_criterion_1,
                             bool emulate_satisfied_criterion_2) {
  std::string bytecode;
  bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit1"),
                            EncodeBool(emulate_satisfied_criterion_1));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit2"),
                            EncodeBool(emulate_satisfied_criterion_2));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_BOOL(GetHash("should_prompt"),
                            EncodeBool(emulate_satisfied_criterion_1 ||
                                       emulate_satisfied_criterion_2));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"),
                            EncodeBool(emulate_satisfied_criterion_1 ||
                                       emulate_satisfied_criterion_2));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("memento_value_in_prefs"));
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestMementoValue));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit2"), VALUE_TRUE);
  bytecode += OP_STORE_BOOL(GetHash("had_prompted_already"), VALUE_TRUE);
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("memento_value_in_local_state"));
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestMementoValue));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit3"), VALUE_TRUE);
  bytecode += OP_STORE_BOOL(GetHash("had_prompted_already"), VALUE_TRUE);
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("memento_value_in_file"));
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestMementoValue));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit4"), VALUE_TRUE);
  bytecode += OP_STORE_BOOL(GetHash("had_prompted_already"), VALUE_TRUE);
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_HASH(GetHash("memento_value_in_prefs"),
                            kTestMementoValue);
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_HASH(GetHash("memento_value_in_local_state"),
                            kTestMementoValue);
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_HASH(GetHash("memento_value_in_file"),
                            kTestMementoValue);
  bytecode += OP_END_OF_SENTENCE;
  return bytecode;
}

// Constructs another evaluation program to specifically test that bits of the
// "satisfied_criteria_mask" are correctly assigned, and so is "should_prompt";
// and that reset is triggered iff the latter is true, regardless of the bits
// in the mask (so as to allow for a non-disjunctive compound criterion).
//
// More specifically, the output of the program will be as follows:
// {
//   "satisfied_criteria_mask_bitN": emulate_satisfied_odd_criteria,
//   "satisfied_criteria_mask_bitM": emulate_satisfied_even_criteria,
//   "combined_status_mask_bit1": emulate_should_prompt,
//   "should_prompt": emulate_should_prompt,
//   "memento_value_in_prefs": kTestMementoValue,
//   "memento_value_in_local_state": kTestMementoValue,
//   "memento_value_in_file": kTestMementoValue
// }
// ... such that N is {1,3,5} and M is {2,4}.
std::string ConstructProgramToExerciseCriteria(
    bool emulate_should_prompt,
    bool emulate_satisfied_odd_criteria,
    bool emulate_satisfied_even_criteria) {
  std::string bytecode;
  bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit1"),
                            EncodeBool(emulate_satisfied_odd_criteria));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit3"),
                            EncodeBool(emulate_satisfied_odd_criteria));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit5"),
                            EncodeBool(emulate_satisfied_odd_criteria));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit2"),
                            EncodeBool(emulate_satisfied_even_criteria));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_BOOL(GetHash("satisfied_criteria_mask_bit4"),
                            EncodeBool(emulate_satisfied_even_criteria));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_BOOL(GetHash("should_prompt"),
                            EncodeBool(emulate_should_prompt));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"),
                            EncodeBool(emulate_should_prompt));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_HASH(GetHash("memento_value_in_prefs"),
                            kTestMementoValue);
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_HASH(GetHash("memento_value_in_local_state"),
                            kTestMementoValue);
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_STORE_HASH(GetHash("memento_value_in_file"),
                            kTestMementoValue);
  bytecode += OP_END_OF_SENTENCE;
  return bytecode;
}

// Constructs another evaluation program to specifically test that local state
// and user preference values are included in the input as expected. We will
// re-purpose the output bitmasks to channel out information about the outcome
// of the checks.
//
// More specifically, the output of the program will be as follows:
// {
//   "combined_status_mask_bit1":
//       (input["preferences.testing.preference"] == kTestPreferenceValue)
//   "combined_status_mask_bit2":
//       (input["local_state.testing.preference"] == kTestPreferenceValue)
//   "combined_status_mask_bit3": input["preferences_iuc.testing.preference"]
//   "combined_status_mask_bit4": input["local_state_iuc.testing.preference"]
// }
std::string ConstructProgramToCheckPreferences() {
  std::string bytecode;
  bytecode += OP_NAVIGATE(GetHash("preferences"));
  bytecode += OP_NAVIGATE(GetHash("testing"));
  bytecode += OP_NAVIGATE(GetHash("preference"));
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestPreferenceValue));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("local_state"));
  bytecode += OP_NAVIGATE(GetHash("testing"));
  bytecode += OP_NAVIGATE(GetHash("preference"));
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestPreferenceValue));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit2"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("preferences_iuc"));
  bytecode += OP_NAVIGATE(GetHash("testing"));
  bytecode += OP_NAVIGATE(GetHash("preference"));
  bytecode += OP_COMPARE_NODE_BOOL(EncodeBool(true));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit3"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("local_state_iuc"));
  bytecode += OP_NAVIGATE(GetHash("testing"));
  bytecode += OP_NAVIGATE(GetHash("preference"));
  bytecode += OP_COMPARE_NODE_BOOL(EncodeBool(true));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit4"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  return bytecode;
}

// Legend for the bitmask returned by the above program.
enum CombinedStatusMaskLegendForCheckingPreferences {
  HAS_EXPECTED_USER_PREFERENCE = 1 << 0,
  HAS_EXPECTED_LOCAL_STATE_PREFERENCE = 1 << 1,
  USER_PREFERENCE_IS_USER_CONTROLLED = 1 << 2,
  LOCAL_STATE_IS_USER_CONTROLLED = 1 << 3,
};

// Constructs yet another evaluation program to specifically test that default
// and pre-populated search engines are included in the input as expected. We
// will re-purpose the output bitmasks to channel out information about the
// outcome of the checks.
//
// More specifically, the output of the program will be as follows:
// {
//   "combined_status_mask_bit1":
//       (input["default_search_provider.search_url"] == kTestSearchURL)
//   "combined_status_mask_bit2": input["default_search_provider_iuc"]
//   "combined_status_mask_bit3":
//       (input["search_providers.*.search_url"] == kTestSearchURL)
//   "combined_status_mask_bit4":
//       (input["search_providers.*.search_url"] == kTestSearchURL2)
// }
std::string ConstructProgramToCheckSearchEngines() {
  std::string bytecode;
  bytecode += OP_NAVIGATE(GetHash("default_search_provider"));
  bytecode += OP_NAVIGATE(GetHash("search_url"));
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestSearchURL));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("default_search_provider_iuc"));
  bytecode += OP_COMPARE_NODE_BOOL(EncodeBool(true));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit2"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("search_providers"));
  bytecode += OP_NAVIGATE_ANY;
  bytecode += OP_NAVIGATE(GetHash("search_url"));
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestSearchURL));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit3"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("search_providers"));
  bytecode += OP_NAVIGATE_ANY;
  bytecode += OP_NAVIGATE(GetHash("search_url"));
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestSearchURL2));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit4"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  return bytecode;
}

// Legend for the bitmask returned by the above program.
enum CombinedStatusMaskLegendForCheckingSearchEngines {
  HAS_EXPECTED_DEFAULT_SEARCH_PROVIDER = 1 << 0,
  DEFAULT_SEARCH_PROVIDER_IS_USER_CONTROLLED = 1 << 1,
  HAS_EXPECTED_PREPOPULATED_SEARCH_PROVIDER_1 = 1 << 2,
  HAS_EXPECTED_PREPOPULATED_SEARCH_PROVIDER_2 = 1 << 3,
};

// Constructs yet another evaluation program to specifically test that loaded
// module digests are included in the input as expected. We will re-purpose the
// output bitmasks to channel out information about the outcome of the checks.
//
// More specifically, the output of the program will be as follows:
// {
//   "combined_status_mask_bit1":
//       (input["loaded_modules.*"] == kTestModuleDigest)
//   "combined_status_mask_bit2":
//       (input["loaded_modules.*"] == kTestModuleDigest2)
// }
std::string ConstructProgramToCheckLoadedModuleDigests() {
  std::string bytecode;
  bytecode += OP_NAVIGATE(GetHash("loaded_modules"));
  bytecode += OP_NAVIGATE_ANY;
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestModuleDigest));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit1"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  bytecode += OP_NAVIGATE(GetHash("loaded_modules"));
  bytecode += OP_NAVIGATE_ANY;
  bytecode += OP_COMPARE_NODE_HASH(GetHash(kTestModuleDigest2));
  bytecode += OP_STORE_BOOL(GetHash("combined_status_mask_bit2"),
                            EncodeBool(true));
  bytecode += OP_END_OF_SENTENCE;
  return bytecode;
}

// Legend for the bitmask returned by the above program.
enum CombinedStatusMaskLegendForCheckingLoadedModules {
  HAS_EXPECTED_MODULE_DIGEST_1 = 1 << 0,
  HAS_EXPECTED_MODULE_DIGEST_2 = 1 << 1,
};

// Test fixtures -------------------------------------------------------------

class AutomaticProfileResetterTestBase : public testing::Test {
 protected:
  explicit AutomaticProfileResetterTestBase(
      const std::string& experiment_group_name)
      : waiting_task_runner_(new base::TestSimpleTaskRunner),
        local_state_(TestingBrowserProcess::GetGlobal()),
        profile_(new TestingProfile()),
        field_trials_(new base::FieldTrialList(NULL)),
        memento_in_prefs_(new PreferenceHostedPromptMemento(profile())),
        memento_in_local_state_(new LocalStateHostedPromptMemento(profile())),
        memento_in_file_(new FileHostedPromptMementoSynchronous(profile())),
        experiment_group_name_(experiment_group_name),
        inject_data_through_variation_params_(false),
        mock_delegate_(NULL) {
    // Make sure the factory is not optimized away, so whatever preferences it
    // wants to register will actually get registered.
    AutomaticProfileResetterFactory::GetInstance();

    // Register some additional local state preferences for testing purposes.
    PrefRegistrySimple* local_state_registry = local_state_.Get()->registry();
    DCHECK(local_state_registry);
    local_state_registry->RegisterStringPref(kTestPreferencePath, "");

    // Register some additional user preferences for testing purposes.
    user_prefs::PrefRegistrySyncable* user_prefs_registry =
        profile_->GetTestingPrefService()->registry();
    DCHECK(user_prefs_registry);
    user_prefs_registry->RegisterStringPref(
        kTestPreferencePath, std::string(),
        user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  }

  virtual void SetUp() OVERRIDE {
    chrome_variations::testing::ClearAllVariationParams();
    base::FieldTrialList::CreateFieldTrial(kAutomaticProfileResetStudyName,
                                           experiment_group_name_);
    resetter_.reset(
        new testing::StrictMock<AutomaticProfileResetterUnderTest>(profile()));
    mock_delegate_owned_.reset(
        new testing::StrictMock<MockProfileResetterDelegate>());
    mock_delegate_ = mock_delegate_owned_.get();

    ExpectAllMementoValuesEqualTo(std::string());
  }

  void SetTestingHashSeed(const std::string& hash_seed) {
    testing_hash_seed_ = hash_seed;
  }

  void SetTestingProgram(const std::string& source_code) {
    testing_program_ = source_code;
  }

  void AllowInjectingTestDataThroughVariationParams(bool value) {
    inject_data_through_variation_params_ = value;
  }

  void ExpectAllMementoValuesEqualTo(const std::string& value) {
    EXPECT_EQ(value, memento_in_prefs_->ReadValue());
    EXPECT_EQ(value, memento_in_local_state_->ReadValue());
    EXPECT_EQ(value, memento_in_file_->ReadValue());
  }

  void UnleashResetterAndWait() {
    if (inject_data_through_variation_params_) {
      std::map<std::string, std::string> variation_params;
      variation_params["program"] = testing_program_;
      variation_params["hash_seed"] = testing_hash_seed_;
      ASSERT_TRUE(chrome_variations::AssociateVariationParams(
          kAutomaticProfileResetStudyName,
          experiment_group_name_,
          variation_params));
    }
    resetter_->Initialize();
    resetter_->SetDelegateForTesting(
        mock_delegate_owned_.PassAs<AutomaticProfileResetterDelegate>());
    resetter_->SetTaskRunnerForWaitingForTesting(waiting_task_runner_);
    if (!inject_data_through_variation_params_) {
      resetter_->SetProgramForTesting(testing_program_);
      resetter_->SetHashSeedForTesting(testing_hash_seed_);
    }
    resetter_->Activate();

    if (waiting_task_runner_->HasPendingTask()) {
      ASSERT_EQ(base::TimeDelta::FromSeconds(55),
                waiting_task_runner_->NextPendingTaskDelay());
      waiting_task_runner_->RunPendingTasks();
    }
    base::RunLoop().RunUntilIdle();
    content::BrowserThread::GetBlockingPool()->FlushForTesting();
    base::RunLoop().RunUntilIdle();
  }

  // Goes through an evaluation flow such that the reset criteria are satisfied.
  // Used to reduce boilerplate for tests that need to verify behavior during
  // the reset prompt flow.
  void OrchestrateThroughEvaluationFlow() {
    SetTestingProgram(ConstructProgram(true, true));
    SetTestingHashSeed(kTestHashSeed);

    mock_delegate().ExpectCallsToDependenciesSetUpMethods();
    mock_delegate().ExpectCallsToGetterMethods();
    mock_delegate().ExpectCallToShowPrompt();
    EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u));

    UnleashResetterAndWait();

    EXPECT_TRUE(resetter().ShouldShowResetBanner());
    testing::Mock::VerifyAndClearExpectations(&resetter());
    testing::Mock::VerifyAndClearExpectations(&mock_delegate());
  }

  // Explicitly shut down the service to double-check that nothing explodes, but
  // first, verify expectations to make sure the service makes no more calls to
  // any mocked functions during or after shutdown.
  void VerifyExpectationsThenShutdownResetter() {
    testing::Mock::VerifyAndClearExpectations(&resetter());
    testing::Mock::VerifyAndClearExpectations(&mock_delegate());

    resetter_->Shutdown();
    resetter_.reset();
  }

  TestingProfile* profile() { return profile_.get(); }
  TestingPrefServiceSimple* local_state() { return local_state_.Get(); }

  PreferenceHostedPromptMemento& memento_in_prefs() {
    return *memento_in_prefs_;
  }

  LocalStateHostedPromptMemento& memento_in_local_state() {
    return *memento_in_local_state_;
  }

  FileHostedPromptMementoSynchronous& memento_in_file() {
    return *memento_in_file_;
  }

  MockProfileResetterDelegate& mock_delegate() { return *mock_delegate_; }
  AutomaticProfileResetterUnderTest& resetter() { return *resetter_; }

 private:
  content::TestBrowserThreadBundle thread_bundle_;
  scoped_refptr<base::TestSimpleTaskRunner> waiting_task_runner_;
  ScopedTestingLocalState local_state_;
  scoped_ptr<TestingProfile> profile_;
  scoped_ptr<base::FieldTrialList> field_trials_;
  scoped_ptr<PreferenceHostedPromptMemento> memento_in_prefs_;
  scoped_ptr<LocalStateHostedPromptMemento> memento_in_local_state_;
  scoped_ptr<FileHostedPromptMementoSynchronous> memento_in_file_;

  std::string experiment_group_name_;
  std::string testing_program_;
  std::string testing_hash_seed_;
  bool inject_data_through_variation_params_;

  scoped_ptr<AutomaticProfileResetterUnderTest> resetter_;
  scoped_ptr<MockProfileResetterDelegate> mock_delegate_owned_;
  MockProfileResetterDelegate* mock_delegate_;

  DISALLOW_COPY_AND_ASSIGN(AutomaticProfileResetterTestBase);
};

class AutomaticProfileResetterTest : public AutomaticProfileResetterTestBase {
 protected:
  AutomaticProfileResetterTest()
      : AutomaticProfileResetterTestBase(kStudyEnabledGroupName) {}
};

class AutomaticProfileResetterTestDryRun
    : public AutomaticProfileResetterTestBase {
 protected:
  AutomaticProfileResetterTestDryRun()
      : AutomaticProfileResetterTestBase(kStudyDryRunGroupName) {}
};

class AutomaticProfileResetterTestDisabled
    : public AutomaticProfileResetterTestBase {
 protected:
  AutomaticProfileResetterTestDisabled()
      : AutomaticProfileResetterTestBase(kStudyDisabledGroupName) {}
};

// Tests ---------------------------------------------------------------------

TEST_F(AutomaticProfileResetterTestDisabled, NothingIsDoneWhenDisabled) {
  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  // No calls are expected to the delegate.

  UnleashResetterAndWait();

  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  ExpectAllMementoValuesEqualTo(std::string());
}

TEST_F(AutomaticProfileResetterTestDryRun, CriteriaNotSatisfied) {
  SetTestingProgram(ConstructProgramToExerciseCriteria(false, true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x1fu, 0x00u));

  UnleashResetterAndWait();

  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  ExpectAllMementoValuesEqualTo(std::string());
}

TEST_F(AutomaticProfileResetterTestDryRun, OddCriteriaSatisfied) {
  SetTestingProgram(ConstructProgramToExerciseCriteria(true, true, false));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x15u, 0x01u));
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_NOT_TRIGGERED));

  UnleashResetterAndWait();

  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTestDryRun, EvenCriteriaSatisfied) {
  SetTestingProgram(ConstructProgramToExerciseCriteria(true, false, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x0au, 0x01u));
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_NOT_TRIGGERED));

  UnleashResetterAndWait();

  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

#if defined(GOOGLE_CHROME_BUILD)
TEST_F(AutomaticProfileResetterTestDryRun, ProgramSetThroughVariationParams) {
  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);
  AllowInjectingTestDataThroughVariationParams(true);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u));
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_NOT_TRIGGERED));

  UnleashResetterAndWait();

  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}
#endif

TEST_F(AutomaticProfileResetterTestDryRun,
       ConditionsSatisfiedAndInvalidMementos) {
  memento_in_prefs().StoreValue(kTestInvalidMementoValue);
  memento_in_local_state().StoreValue(kTestInvalidMementoValue);
  memento_in_file().StoreValue(kTestInvalidMementoValue);

  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u));
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_NOT_TRIGGERED));

  UnleashResetterAndWait();

  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTestDryRun, AlreadyHadPrefHostedMemento) {
  memento_in_prefs().StoreValue(kTestMementoValue);

  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x03u));

  UnleashResetterAndWait();

  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  EXPECT_EQ(kTestMementoValue, memento_in_prefs().ReadValue());
  EXPECT_EQ(std::string(), memento_in_local_state().ReadValue());
  EXPECT_EQ(std::string(), memento_in_file().ReadValue());
}

TEST_F(AutomaticProfileResetterTestDryRun, AlreadyHadLocalStateHostedMemento) {
  memento_in_local_state().StoreValue(kTestMementoValue);

  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x05u));

  UnleashResetterAndWait();

  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  EXPECT_EQ(std::string(), memento_in_prefs().ReadValue());
  EXPECT_EQ(kTestMementoValue, memento_in_local_state().ReadValue());
  EXPECT_EQ(std::string(), memento_in_file().ReadValue());
}

TEST_F(AutomaticProfileResetterTestDryRun, AlreadyHadFileHostedMemento) {
  memento_in_file().StoreValue(kTestMementoValue);

  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x09u));

  UnleashResetterAndWait();

  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  EXPECT_EQ(std::string(), memento_in_prefs().ReadValue());
  EXPECT_EQ(std::string(), memento_in_local_state().ReadValue());
  EXPECT_EQ(kTestMementoValue, memento_in_file().ReadValue());
}

TEST_F(AutomaticProfileResetterTestDryRun, DoNothingWhenResourcesAreMissing) {
  SetTestingProgram(std::string());
  SetTestingHashSeed(std::string());

  // No calls are expected to the delegate.

  UnleashResetterAndWait();

  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  ExpectAllMementoValuesEqualTo(std::string());
}

TEST_F(AutomaticProfileResetterTest, CriteriaNotSatisfied) {
  SetTestingProgram(ConstructProgramToExerciseCriteria(false, true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x1fu, 0x00u));

  UnleashResetterAndWait();

  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  ExpectAllMementoValuesEqualTo(std::string());
}

TEST_F(AutomaticProfileResetterTest, OddCriteriaSatisfied) {
  SetTestingProgram(ConstructProgramToExerciseCriteria(true, true, false));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  mock_delegate().ExpectCallToShowPrompt();
  EXPECT_CALL(resetter(), ReportStatistics(0x15u, 0x01u));

  UnleashResetterAndWait();

  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, EvenCriteriaSatisfied) {
  SetTestingProgram(ConstructProgramToExerciseCriteria(true, false, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  mock_delegate().ExpectCallToShowPrompt();
  EXPECT_CALL(resetter(), ReportStatistics(0x0au, 0x01u));

  UnleashResetterAndWait();

  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

#if defined(GOOGLE_CHROME_BUILD)
TEST_F(AutomaticProfileResetterTest, ProgramSetThroughVariationParams) {
  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);
  AllowInjectingTestDataThroughVariationParams(true);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  mock_delegate().ExpectCallToShowPrompt();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u));
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));

  UnleashResetterAndWait();
  resetter().NotifyDidShowResetBubble();

  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}
#endif

TEST_F(AutomaticProfileResetterTest, ConditionsSatisfiedAndInvalidMementos) {
  memento_in_prefs().StoreValue(kTestInvalidMementoValue);
  memento_in_local_state().StoreValue(kTestInvalidMementoValue);
  memento_in_file().StoreValue(kTestInvalidMementoValue);

  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  mock_delegate().ExpectCallToShowPrompt();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u));
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));

  UnleashResetterAndWait();
  resetter().NotifyDidShowResetBubble();

  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PrefHostedMementoPreventsPrompt) {
  memento_in_prefs().StoreValue(kTestMementoValue);

  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x03u));

  UnleashResetterAndWait();

  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  EXPECT_EQ(kTestMementoValue, memento_in_prefs().ReadValue());
  EXPECT_EQ(std::string(), memento_in_local_state().ReadValue());
  EXPECT_EQ(std::string(), memento_in_file().ReadValue());
}

TEST_F(AutomaticProfileResetterTest, LocalStateHostedMementoPreventsPrompt) {
  memento_in_local_state().StoreValue(kTestMementoValue);

  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x05u));

  UnleashResetterAndWait();

  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  EXPECT_EQ(std::string(), memento_in_prefs().ReadValue());
  EXPECT_EQ(kTestMementoValue, memento_in_local_state().ReadValue());
  EXPECT_EQ(std::string(), memento_in_file().ReadValue());
}

TEST_F(AutomaticProfileResetterTest, FileHostedMementoPreventsPrompt) {
  memento_in_file().StoreValue(kTestMementoValue);

  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x09u));

  UnleashResetterAndWait();

  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  EXPECT_EQ(std::string(), memento_in_prefs().ReadValue());
  EXPECT_EQ(std::string(), memento_in_local_state().ReadValue());
  EXPECT_EQ(kTestMementoValue, memento_in_file().ReadValue());
}

TEST_F(AutomaticProfileResetterTest, DoNothingWhenResourcesAreMissing) {
  SetTestingProgram(std::string());
  SetTestingHashSeed(std::string());

  // No calls are expected to the delegate.

  UnleashResetterAndWait();

  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  ExpectAllMementoValuesEqualTo(std::string());
}

TEST_F(AutomaticProfileResetterTest, PromptSuppressed) {
  OrchestrateThroughEvaluationFlow();

  VerifyExpectationsThenShutdownResetter();

  ExpectAllMementoValuesEqualTo(std::string());
}

TEST_F(AutomaticProfileResetterTest, PromptNotSupported) {
  SetTestingProgram(ConstructProgram(true, true));
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  EXPECT_CALL(mock_delegate(), TriggerPrompt())
      .WillOnce(testing::Return(false));
  EXPECT_CALL(resetter(), ReportStatistics(0x03u, 0x01u));
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_NOT_TRIGGERED));

  UnleashResetterAndWait();

  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PromptIgnored) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));
  resetter().NotifyDidShowResetBubble();
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PromptActionReset) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));
  resetter().NotifyDidShowResetBubble();
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  testing::Mock::VerifyAndClearExpectations(&resetter());

  mock_delegate().ExpectCallToTriggerReset(false);
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_ACTION_RESET));
  resetter().TriggerProfileReset(false /*send_feedback*/);
  testing::Mock::VerifyAndClearExpectations(&resetter());
  testing::Mock::VerifyAndClearExpectations(&mock_delegate());

  EXPECT_CALL(mock_delegate(), DismissPrompt());
  mock_delegate().EmulateProfileResetCompleted();
  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PromptActionResetWithFeedback) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));
  resetter().NotifyDidShowResetBubble();
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  testing::Mock::VerifyAndClearExpectations(&resetter());

  mock_delegate().ExpectCallToTriggerReset(true);
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_ACTION_RESET));
  resetter().TriggerProfileReset(true /*send_feedback*/);
  testing::Mock::VerifyAndClearExpectations(&resetter());
  testing::Mock::VerifyAndClearExpectations(&mock_delegate());

  EXPECT_CALL(mock_delegate(), DismissPrompt());
  mock_delegate().EmulateProfileResetCompleted();
  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PromptActionNoReset) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));
  resetter().NotifyDidShowResetBubble();
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  testing::Mock::VerifyAndClearExpectations(&resetter());

  EXPECT_CALL(mock_delegate(), DismissPrompt());
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_ACTION_NO_RESET));
  resetter().SkipProfileReset();
  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PromptFollowedByWebUIReset) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));
  resetter().NotifyDidShowResetBubble();
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  testing::Mock::VerifyAndClearExpectations(&resetter());

  EXPECT_CALL(mock_delegate(), DismissPrompt());
  resetter().NotifyDidOpenWebUIResetDialog();
  testing::Mock::VerifyAndClearExpectations(&mock_delegate());

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_FOLLOWED_BY_WEBUI_RESET));
  resetter().NotifyDidCloseWebUIResetDialog(true);
  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PromptFollowedByWebUINoReset) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));
  resetter().NotifyDidShowResetBubble();
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  testing::Mock::VerifyAndClearExpectations(&resetter());

  EXPECT_CALL(mock_delegate(), DismissPrompt());
  resetter().NotifyDidOpenWebUIResetDialog();
  testing::Mock::VerifyAndClearExpectations(&mock_delegate());

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_FOLLOWED_BY_WEBUI_NO_RESET));
  resetter().NotifyDidCloseWebUIResetDialog(false);
  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PromptFollowedByIncidentalWebUIReset) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));
  resetter().NotifyDidShowResetBubble();
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  testing::Mock::VerifyAndClearExpectations(&resetter());

  // Missing NotifyDidOpenWebUIResetDialog().
  // This can arise if a settings page was already opened at the time the prompt
  // was triggered, and this already opened dialog was used to initiate a reset
  // after having dismissed the prompt.

  EXPECT_CALL(mock_delegate(), DismissPrompt());
  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_FOLLOWED_BY_WEBUI_RESET));
  resetter().NotifyDidCloseWebUIResetDialog(true);
  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PromptSuppressedButHadWebUIReset) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(mock_delegate(), DismissPrompt());
  resetter().NotifyDidOpenWebUIResetDialog();
  testing::Mock::VerifyAndClearExpectations(&mock_delegate());

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_RESET));
  resetter().NotifyDidCloseWebUIResetDialog(true);
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, PromptSuppressedButHadWebUINoReset) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(mock_delegate(), DismissPrompt());
  resetter().NotifyDidOpenWebUIResetDialog();
  testing::Mock::VerifyAndClearExpectations(&mock_delegate());

  EXPECT_CALL(resetter(), ReportPromptResult(AutomaticProfileResetter::
      PROMPT_NOT_SHOWN_BUBBLE_BUT_HAD_WEBUI_NO_RESET));
  resetter().NotifyDidCloseWebUIResetDialog(false);
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  EXPECT_TRUE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, BannerDismissed) {
  OrchestrateThroughEvaluationFlow();

  EXPECT_CALL(resetter(), ReportPromptResult(
      AutomaticProfileResetter::PROMPT_SHOWN_BUBBLE));
  resetter().NotifyDidShowResetBubble();
  ExpectAllMementoValuesEqualTo(kTestMementoValue);
  testing::Mock::VerifyAndClearExpectations(&resetter());

  resetter().NotifyDidCloseWebUIResetBanner();

  EXPECT_TRUE(resetter().IsResetPromptFlowActive());
  EXPECT_FALSE(resetter().ShouldShowResetBanner());

  // Note: we use strict mocks, so this also checks the bubble is not closed.
  VerifyExpectationsThenShutdownResetter();
}

TEST_F(AutomaticProfileResetterTest, BannerDismissedWhilePromptSuppressed) {
  OrchestrateThroughEvaluationFlow();

  resetter().NotifyDidCloseWebUIResetBanner();

  EXPECT_TRUE(resetter().IsResetPromptFlowActive());
  EXPECT_FALSE(resetter().ShouldShowResetBanner());
  VerifyExpectationsThenShutdownResetter();

  ExpectAllMementoValuesEqualTo(std::string());
}

// Please see comments above ConstructProgramToCheckPreferences() to understand
// how the following tests work.

TEST_F(AutomaticProfileResetterTest, InputUserPreferencesCorrect) {
  SetTestingProgram(ConstructProgramToCheckPreferences());
  SetTestingHashSeed(kTestHashSeed);

  PrefService* prefs = profile()->GetPrefs();
  prefs->SetString(kTestPreferencePath, kTestPreferenceValue);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  uint32 expected_mask = HAS_EXPECTED_USER_PREFERENCE |
                         USER_PREFERENCE_IS_USER_CONTROLLED;
  EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask));

  UnleashResetterAndWait();
}

TEST_F(AutomaticProfileResetterTest, InputLocalStateCorrect) {
  SetTestingProgram(ConstructProgramToCheckPreferences());
  SetTestingHashSeed(kTestHashSeed);

  PrefService* prefs = local_state();
  prefs->SetString(kTestPreferencePath, kTestPreferenceValue);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  uint32 expected_mask = HAS_EXPECTED_LOCAL_STATE_PREFERENCE |
                         LOCAL_STATE_IS_USER_CONTROLLED;
  EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask));

  UnleashResetterAndWait();
}

TEST_F(AutomaticProfileResetterTest, InputManagedUserPreferencesCorrect) {
  SetTestingProgram(ConstructProgramToCheckPreferences());
  SetTestingHashSeed(kTestHashSeed);

  TestingPrefServiceSyncable* prefs = profile()->GetTestingPrefService();
  prefs->SetManagedPref(kTestPreferencePath,
                        new base::StringValue(kTestPreferenceValue));

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  uint32 expected_mask = HAS_EXPECTED_USER_PREFERENCE;
  EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask));

  UnleashResetterAndWait();
}

TEST_F(AutomaticProfileResetterTest, InputManagedLocalStateCorrect) {
  SetTestingProgram(ConstructProgramToCheckPreferences());
  SetTestingHashSeed(kTestHashSeed);

  TestingPrefServiceSimple* prefs = local_state();
  prefs->SetManagedPref(kTestPreferencePath,
                        new base::StringValue(kTestPreferenceValue));

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  uint32 expected_mask = HAS_EXPECTED_LOCAL_STATE_PREFERENCE;
  EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask));

  UnleashResetterAndWait();
}

// Please see comments above ConstructProgramToCheckSearchEngines() to
// understand how the following tests work.

TEST_F(AutomaticProfileResetterTest, InputDefaultSearchProviderCorrect) {
  SetTestingProgram(ConstructProgramToCheckSearchEngines());
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().emulated_default_search_provider_details().SetString(
      kSearchURLAttributeKey, kTestSearchURL);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  uint32 expected_mask = HAS_EXPECTED_DEFAULT_SEARCH_PROVIDER |
                         DEFAULT_SEARCH_PROVIDER_IS_USER_CONTROLLED;
  EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask));

  UnleashResetterAndWait();
}

TEST_F(AutomaticProfileResetterTest, InputSearchProviderManagedCorrect) {
  SetTestingProgram(ConstructProgramToCheckSearchEngines());
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().emulated_default_search_provider_details().SetString(
      kSearchURLAttributeKey, kTestSearchURL);
  mock_delegate().set_emulated_is_default_search_provider_managed(true);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  uint32 expected_mask = HAS_EXPECTED_DEFAULT_SEARCH_PROVIDER;
  EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask));

  UnleashResetterAndWait();
}

TEST_F(AutomaticProfileResetterTest, InputSearchProvidersCorrect) {
  SetTestingProgram(ConstructProgramToCheckSearchEngines());
  SetTestingHashSeed(kTestHashSeed);

  base::DictionaryValue* search_provider_1 = new base::DictionaryValue;
  base::DictionaryValue* search_provider_2 = new base::DictionaryValue;
  search_provider_1->SetString(kSearchURLAttributeKey, kTestSearchURL);
  search_provider_2->SetString(kSearchURLAttributeKey, kTestSearchURL2);
  mock_delegate().emulated_search_providers_details().Append(search_provider_1);
  mock_delegate().emulated_search_providers_details().Append(search_provider_2);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  uint32 expected_mask = DEFAULT_SEARCH_PROVIDER_IS_USER_CONTROLLED |
                         HAS_EXPECTED_PREPOPULATED_SEARCH_PROVIDER_1 |
                         HAS_EXPECTED_PREPOPULATED_SEARCH_PROVIDER_2;
  EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask));

  UnleashResetterAndWait();
}

// Please see comments above ConstructProgramToCheckLoadedModuleDigests() to
// understand how the following tests work.

TEST_F(AutomaticProfileResetterTest, InputModuleDigestsCorrect) {
  SetTestingProgram(ConstructProgramToCheckLoadedModuleDigests());
  SetTestingHashSeed(kTestHashSeed);

  mock_delegate().emulated_loaded_module_digests().AppendString(
      kTestModuleDigest);
  mock_delegate().emulated_loaded_module_digests().AppendString(
      kTestModuleDigest2);

  mock_delegate().ExpectCallsToDependenciesSetUpMethods();
  mock_delegate().ExpectCallsToGetterMethods();
  uint32 expected_mask =
      HAS_EXPECTED_MODULE_DIGEST_1 | HAS_EXPECTED_MODULE_DIGEST_2;
  EXPECT_CALL(resetter(), ReportStatistics(0x00u, expected_mask));

  UnleashResetterAndWait();
}

}  // namespace

/* [<][>][^][v][top][bottom][index][help] */