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

Unified Diff: chrome/browser/profiles/profile_statistics_browsertest.cc

Issue 1579433002: Make profile statistics tasks inspectable by tests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make ProfileStatisticsAggregator tasks trackable Created 4 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/profiles/profile_statistics_browsertest.cc
diff --git a/chrome/browser/profiles/profile_statistics_browsertest.cc b/chrome/browser/profiles/profile_statistics_browsertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0189643c6b681977798f84d94bb26d433ea82f0b
--- /dev/null
+++ b/chrome/browser/profiles/profile_statistics_browsertest.cc
@@ -0,0 +1,288 @@
+// Copyright (c) 2012 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 <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_statistics.h"
+#include "chrome/browser/profiles/profile_statistics_aggregator.h"
+#include "chrome/browser/profiles/profile_statistics_constants.h"
+#include "chrome/browser/profiles/profile_statistics_types.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/test_password_store.h"
+#include "content/public/test/test_utils.h"
+
+namespace {
+
+const std::set<std::string> stats_categories {
+ profiles::kProfileStatisticsBrowsingHistory,
+ profiles::kProfileStatisticsPasswords,
+ profiles::kProfileStatisticsBookmarks,
+ profiles::kProfileStatisticsSettings};
+
+const size_t num_of_stats_categories = stats_categories.size();
+
+bool IsProfileCategoryStatEqual(const profiles::ProfileCategoryStat& a,
+ const profiles::ProfileCategoryStat& b) {
+ return a.category == b.category && a.count == b.count &&
+ a.success == b.success;
+}
+
+std::string ProfileCategoryStatToString(
+ const profiles::ProfileCategoryStat& a) {
+ return base::StringPrintf("category = %s, count = %d, success = %s",
+ a.category.c_str(), a.count, a.success ? "true" : "false");
+}
+
+::testing::AssertionResult AssertionProfileCategoryStatEqual(
+ const char* actual_expression,
+ const char* expected_expression,
+ const profiles::ProfileCategoryStat& actual_value,
+ const profiles::ProfileCategoryStat& expected_value) {
+ if (IsProfileCategoryStatEqual(actual_value, expected_value)) {
+ return ::testing::AssertionSuccess();
+ } else {
+ return ::testing::AssertionFailure()
+ << "Value of: " << actual_expression
+ << "\n Actual: " << ProfileCategoryStatToString(actual_value)
+ << "\nExpected: " << expected_expression
+ << "\nWhich is: " << ProfileCategoryStatToString(expected_value);
+ }
+}
+
+::testing::AssertionResult AssertionProfileCategoryStatsEqual(
+ const char* actual_expression,
+ const char* expected_expression,
+ const profiles::ProfileCategoryStats& actual_value,
+ const profiles::ProfileCategoryStats& expected_value) {
+ size_t actual_count = actual_value.size();
+ size_t expected_count = expected_value.size();
+ std::vector<bool> actual_unused(actual_count, true);
+ std::vector<bool> expected_unused(expected_count, true);
+
+ bool match_failed = actual_count != expected_count;
+ for (size_t actual_pos = 0; actual_pos < actual_count; actual_pos++) {
+ for (size_t expected_pos = 0; expected_pos < expected_count;
+ expected_pos++) {
+ if (expected_unused[expected_pos] &&
+ IsProfileCategoryStatEqual(actual_value[actual_pos],
+ expected_value[expected_pos])) {
+ actual_unused[actual_pos] = false;
+ expected_unused[expected_pos] = false;
+ break;
+ }
+ }
+
+ if (actual_unused[actual_pos])
+ match_failed = true;
+ }
+
+ if (!match_failed) {
+ return ::testing::AssertionSuccess();
+ } else {
+ ::testing::AssertionResult result = testing::AssertionFailure();
+ result << "ProfileCategoryStats are not equal.";
+
+ result << "\n Actual: " << actual_expression;
+ bool actual_printed = false;
+ for (size_t i = 0; i < actual_count; i++) {
+ if (actual_unused[i]) {
+ result << "\n"
+ << (actual_printed ? " " : "Unmatched rows: ")
+ << ProfileCategoryStatToString(actual_value[i]);
+ actual_printed = true;
+ }
+ }
+ if (!actual_printed)
+ result << "(no unmatched rows found in actual value)";
+
+
+ result << "\nExpected: " << expected_expression;
+ bool expected_printed = false;
+ for (size_t i = 0; i < expected_count; i++) {
+ if (expected_unused[i]) {
+ result << "\n"
+ << (expected_printed ? " " : "Unmatched rows: ")
+ << ProfileCategoryStatToString(expected_value[i]);
+ expected_printed = true;
+ }
+ }
+ if (!expected_printed)
+ result << "(no unmatched rows found in expected value)";
+
+ return result;
+ }
+}
+
+class ProfileStatisticsAggregatorState {
+ public:
+ explicit ProfileStatisticsAggregatorState(base::RunLoop* run_loop)
+ : run_loop_(run_loop) {}
+
+ ProfileStatisticsAggregatorState(base::RunLoop* run_loop,
+ size_t required_stat_count)
+ : run_loop_(run_loop),
+ required_stat_count_(
+ std::min(num_of_stats_categories, required_stat_count)) {}
+
+ void callback(profiles::ProfileCategoryStats stats_return) {
+ size_t newCount = stats_return.size();
+ // If newCount is 1, then a new GatherStatistics task has started. Discard
+ // the old statistics by setting oldCount to 0 in this case.
+ size_t oldCount = newCount == 1 ? 0 : stats_.size();
+
+ EXPECT_LT(oldCount, newCount);
+ if (oldCount < newCount) {
+ for (size_t i = 0; i < oldCount; i++) {
+ // Exisiting statistics must be the same.
+ EXPECT_PRED_FORMAT2(AssertionProfileCategoryStatEqual,
+ stats_[i], stats_return[i]);
+ // The new statistic categories must be different.
+ for (size_t j = oldCount; j < newCount; j++)
+ EXPECT_NE(stats_[i].category, stats_return[j].category);
+ }
+
+ for (size_t j = oldCount; j < newCount; j++) {
+ EXPECT_EQ(1u, stats_categories.count(stats_return[j].category));
+ // Count the number of statistics failures (incrementally).
+ if (!stats_return[j].success)
+ num_of_fails_++;
+ }
+ }
+ stats_ = stats_return;
+
+ EXPECT_GE(num_of_stats_categories, newCount);
+ if (required_stat_count_ <= newCount)
+ run_loop_->Quit();
+ }
+
+ profiles::ProfileCategoryStats GetStats() const { return stats_; }
+ int GetNumOfFails() const { return num_of_fails_; }
+ void SetRunLoopAndRequiredStatCount(base::RunLoop* run_loop,
+ size_t required_stat_count) {
+ run_loop_ = run_loop;
+ required_stat_count_ = std::min(num_of_stats_categories,
+ required_stat_count);
+ }
+
+ private:
+ profiles::ProfileCategoryStats stats_;
+ int num_of_fails_ = 0;
+ base::RunLoop* run_loop_;
+ size_t required_stat_count_ = num_of_stats_categories;
+};
+
+void WaitMilliseconds(int time_in_milliseconds) {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(time_in_milliseconds));
+ run_loop.Run();
+}
+
+} // namespace
+
+class ProfileStatisticsBrowserTest : public InProcessBrowserTest {
+ public:
+ void SetUpOnMainThread() override {
+ // Use TestPasswordStore to remove a possible race. Normally the
+ // PasswordStore does its database manipulation on the DB thread, which
+ // creates a possible race during navigation. Specifically the
+ // PasswordManager will ignore any forms in a page if the load from the
+ // PasswordStore has not completed.
+ PasswordStoreFactory::GetInstance()->SetTestingFactory(
+ browser()->profile(),
+ password_manager::BuildPasswordStore<
+ content::BrowserContext, password_manager::TestPasswordStore>);
+ }
+};
+
+using ProfileStatisticsBrowserDeathTest = ProfileStatisticsBrowserTest;
+
+IN_PROC_BROWSER_TEST_F(ProfileStatisticsBrowserTest, GatherStatistics) {
+ Profile* profile = ProfileManager::GetActiveUserProfile();
+ ASSERT_TRUE(profile);
+
+ base::RunLoop run_loop;
+ ProfileStatisticsAggregatorState state(&run_loop);
+ EXPECT_EQ(false, ProfileStatistics::HasAggregator(profile));
+ ProfileStatistics::GatherProfileStatistics(
+ profile,
+ base::Bind(&ProfileStatisticsAggregatorState::callback,
+ base::Unretained(&state)));
+ EXPECT_EQ(true, ProfileStatistics::HasAggregator(profile));
+ EXPECT_EQ(1u, ProfileStatistics::GetAggregator(profile)->GetCallbackCount());
+ run_loop.Run();
+
+ EXPECT_EQ(0, state.GetNumOfFails());
+
+ profiles::ProfileCategoryStats stats = state.GetStats();
+ for (const auto& stat : stats) {
+ if (stat.category != profiles::kProfileStatisticsSettings)
+ EXPECT_EQ(0, stat.count);
+ }
+
+ EXPECT_PRED_FORMAT2(AssertionProfileCategoryStatsEqual, stats,
+ ProfileStatistics::GetProfileStatisticsFromCache(profile->GetPath()));
+}
+
+IN_PROC_BROWSER_TEST_F(ProfileStatisticsBrowserTest,
+ GatherStatisticsTwoCallbacks) {
+ Profile* profile = ProfileManager::GetActiveUserProfile();
+ ASSERT_TRUE(profile);
+
+ base::RunLoop run_loop1a;
+ base::RunLoop run_loop1b;
+ base::RunLoop run_loop2;
+ ProfileStatisticsAggregatorState state1(&run_loop1a, 1u);
+ ProfileStatisticsAggregatorState state2(&run_loop2);
+
+ EXPECT_EQ(false, ProfileStatistics::HasAggregator(profile));
+ ProfileStatistics::GatherProfileStatistics(
+ profile,
+ base::Bind(&ProfileStatisticsAggregatorState::callback,
+ base::Unretained(&state1)));
+ EXPECT_EQ(true, ProfileStatistics::HasAggregator(profile));
+ EXPECT_EQ(1u, ProfileStatistics::GetAggregator(profile)->GetCallbackCount());
+ run_loop1a.Run();
+
+ state1.SetRunLoopAndRequiredStatCount(&run_loop1b, SIZE_MAX);
+
+ ProfileStatistics::GatherProfileStatistics(
+ profile,
+ base::Bind(&ProfileStatisticsAggregatorState::callback,
+ base::Unretained(&state2)));
+ EXPECT_EQ(true, ProfileStatistics::HasAggregator(profile));
+ EXPECT_EQ(2u, ProfileStatistics::GetAggregator(profile)->GetCallbackCount());
+ run_loop1b.Run();
+ run_loop2.Run();
+
+ EXPECT_EQ(0, state1.GetNumOfFails());
+
+ EXPECT_PRED_FORMAT2(AssertionProfileCategoryStatsEqual,
+ state1.GetStats(), state2.GetStats());
+}
+
+IN_PROC_BROWSER_TEST_F(ProfileStatisticsBrowserTest, CloseBrowser) {
+ Profile* profile = ProfileManager::GetActiveUserProfile();
+ ASSERT_TRUE(profile);
+
+ EXPECT_EQ(false, ProfileStatistics::HasAggregator(profile));
+ CloseBrowserSynchronously(browser());
+ EXPECT_EQ(true, ProfileStatistics::HasAggregator(profile));
+ EXPECT_EQ(0u, ProfileStatistics::GetAggregator(profile)->GetCallbackCount());
+}

Powered by Google App Engine
This is Rietveld 408576698