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

Side by Side 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: Changed gyp/gn files, also a few small changes Created 4 years, 9 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 (c) 2016 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 <stddef.h>
6 #include <stdint.h>
7
8 #include <algorithm>
9 #include <set>
10 #include <string>
11 #include <vector>
12
13 #include "base/bind.h"
14 #include "base/callback_forward.h"
15 #include "base/macros.h"
16 #include "base/strings/stringprintf.h"
17 #include "build/build_config.h"
18 #include "chrome/browser/password_manager/password_store_factory.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/profiles/profile_statistics.h"
21 #include "chrome/browser/profiles/profile_statistics_aggregator.h"
22 #include "chrome/browser/profiles/profile_statistics_constants.h"
23 #include "chrome/browser/profiles/profile_statistics_factory.h"
24 #include "chrome/browser/profiles/profile_statistics_types.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/test/base/in_process_browser_test.h"
27 #include "components/password_manager/core/browser/password_manager_test_utils.h "
28 #include "components/password_manager/core/browser/test_password_store.h"
29 #include "content/public/test/test_utils.h"
30
31 namespace {
32
33 std::set<std::string> stats_categories() {
34 std::set<std::string> categories;
35 categories.insert(profiles::kProfileStatisticsBrowsingHistory);
36 categories.insert(profiles::kProfileStatisticsPasswords);
37 categories.insert(profiles::kProfileStatisticsBookmarks);
38 categories.insert(profiles::kProfileStatisticsSettings);
39 EXPECT_EQ(4u, categories.size());
40 return categories;
41 }
42
43 bool IsProfileCategoryStatEqual(const profiles::ProfileCategoryStat& a,
44 const profiles::ProfileCategoryStat& b) {
45 return a.category == b.category && a.count == b.count &&
46 a.success == b.success;
47 }
48
49 std::string ProfileCategoryStatToString(
50 const profiles::ProfileCategoryStat& a) {
51 return base::StringPrintf("category = %s, count = %d, success = %s",
52 a.category.c_str(), a.count, a.success ? "true" : "false");
53 }
54
55 ::testing::AssertionResult AssertionProfileCategoryStatEqual(
56 const char* actual_expression,
57 const char* expected_expression,
58 const profiles::ProfileCategoryStat& actual_value,
59 const profiles::ProfileCategoryStat& expected_value) {
60 if (IsProfileCategoryStatEqual(actual_value, expected_value)) {
61 return ::testing::AssertionSuccess();
62 } else {
63 return ::testing::AssertionFailure()
64 << "Value of: " << actual_expression
65 << "\n Actual: " << ProfileCategoryStatToString(actual_value)
66 << "\nExpected: " << expected_expression
67 << "\nWhich is: " << ProfileCategoryStatToString(expected_value);
68 }
69 }
70
71 ::testing::AssertionResult AssertionProfileCategoryStatsEqual(
72 const char* actual_expression,
73 const char* expected_expression,
74 const profiles::ProfileCategoryStats& actual_value,
75 const profiles::ProfileCategoryStats& expected_value) {
76 if (std::is_permutation(actual_value.cbegin(),
77 actual_value.cend(),
78 expected_value.cbegin(),
79 expected_value.cend(),
80 IsProfileCategoryStatEqual)) {
81 return ::testing::AssertionSuccess();
82 } else {
83 ::testing::AssertionResult result = testing::AssertionFailure();
84 result << "ProfileCategoryStats are not equal.";
85
86 result << "\n Actual: " << actual_expression << "\nWhich is:";
87 for (const auto& value : actual_value)
88 result << "\n " << ProfileCategoryStatToString(value);
89
90 result << "\nExpected: " << expected_expression << "\nWhich is:";
91 for (const auto& value : expected_value)
92 result << "\n " << ProfileCategoryStatToString(value);
93
94 return result;
95 }
96 }
97
98 class ProfileStatisticsAggregatorState {
99 public:
100 explicit ProfileStatisticsAggregatorState(const base::Closure& quit_closure)
101 : ProfileStatisticsAggregatorState(quit_closure,
102 stats_categories().size()) {}
103
104 ProfileStatisticsAggregatorState(const base::Closure& quit_closure,
105 size_t required_stat_count) {
106 stats_categories_ = stats_categories();
107 num_of_stats_categories_ = stats_categories_.size();
108 SetQuitClosureAndRequiredStatCount(quit_closure, required_stat_count);
109 }
110
111 void SetQuitClosureAndRequiredStatCount(const base::Closure& quit_closure,
112 size_t required_stat_count) {
113 EXPECT_FALSE(quit_closure.is_null());
114 quit_closure_ = quit_closure;
115 EXPECT_GE(num_of_stats_categories_, required_stat_count);
116 required_stat_count_ = required_stat_count;
117 }
118
119 profiles::ProfileCategoryStats GetStats() const { return stats_; }
120 int GetNumOfFails() const { return num_of_fails_; }
121
122 void StatsCallback(profiles::ProfileCategoryStats stats_return) {
123 size_t newCount = stats_return.size();
124 // If newCount is 1, then a new GatherStatistics task has started. Discard
125 // the old statistics by setting oldCount to 0 in this case.
126 size_t oldCount = newCount == 1u ? 0u : stats_.size();
127
128 // Only one new statistic arrives at a time.
129 EXPECT_EQ(oldCount + 1u, newCount);
130 for (size_t i = 0u; i < oldCount; i++) {
131 // Exisiting statistics must be the same.
132 EXPECT_PRED_FORMAT2(AssertionProfileCategoryStatEqual,
133 stats_[i], stats_return[i]);
134 }
135
136 num_of_fails_ = 0;
137 for (size_t i = 0u; i < newCount; i++) {
138 // The category must be a valid category.
139 EXPECT_EQ(1u, stats_categories_.count(stats_return[i].category));
140 // The categories in |stats_return| must all different.
141 for (size_t j = 0u; j < i; j++)
142 EXPECT_NE(stats_return[i].category, stats_return[j].category);
143 // Count the number of statistics failures.
144 if (!stats_return[i].success)
145 num_of_fails_++;
146 }
147 stats_ = stats_return;
148
149 EXPECT_GE(num_of_stats_categories_, newCount);
150 if (required_stat_count_ <= newCount)
151 quit_closure_.Run();
152 }
153
154 private:
155 std::set<std::string> stats_categories_;
156 base::Closure quit_closure_;
157 size_t num_of_stats_categories_;
158 size_t required_stat_count_;
159
160 profiles::ProfileCategoryStats stats_;
161 int num_of_fails_ = 0;
162 };
163
164 } // namespace
165
166 class ProfileStatisticsBrowserTest : public InProcessBrowserTest {
167 public:
168 void SetUpOnMainThread() override {
169 // Use TestPasswordStore to remove a possible race. Normally the
170 // PasswordStore does its database manipulation on the DB thread, which
171 // creates a possible race during navigation. Specifically the
172 // PasswordManager will ignore any forms in a page if the load from the
173 // PasswordStore has not completed.
174 PasswordStoreFactory::GetInstance()->SetTestingFactory(
175 browser()->profile(),
176 password_manager::BuildPasswordStore<
177 content::BrowserContext, password_manager::TestPasswordStore>);
178 }
179 };
180
181 using ProfileStatisticsBrowserDeathTest = ProfileStatisticsBrowserTest;
182
183 IN_PROC_BROWSER_TEST_F(ProfileStatisticsBrowserTest, GatherStatistics) {
184 Profile* profile = ProfileManager::GetActiveUserProfile();
185 ASSERT_TRUE(profile);
186 ProfileStatistics* profile_stat =
187 ProfileStatisticsFactory::GetForProfile(profile);
188
189 scoped_refptr<content::MessageLoopRunner> loop =
190 new content::MessageLoopRunner;
191 ProfileStatisticsAggregatorState state(loop->QuitClosure());
192 EXPECT_FALSE(profile_stat->HasAggregator());
193 profile_stat->GatherStatistics(
194 base::Bind(&ProfileStatisticsAggregatorState::StatsCallback,
195 base::Unretained(&state)));
196 ASSERT_TRUE(profile_stat->HasAggregator());
197 EXPECT_EQ(1u, profile_stat->GetAggregator()->GetCallbackCount());
198 loop->Run();
199
200 EXPECT_EQ(0, state.GetNumOfFails());
201
202 profiles::ProfileCategoryStats stats = state.GetStats();
203 for (const auto& stat : stats) {
204 if (stat.category != profiles::kProfileStatisticsSettings)
205 EXPECT_EQ(0, stat.count);
206 }
207
208 EXPECT_PRED_FORMAT2(AssertionProfileCategoryStatsEqual, stats,
209 ProfileStatistics::GetProfileStatisticsFromCache(profile->GetPath()));
210 }
211
212 IN_PROC_BROWSER_TEST_F(ProfileStatisticsBrowserTest,
213 GatherStatisticsTwoCallbacks) {
214 Profile* profile = ProfileManager::GetActiveUserProfile();
215 ASSERT_TRUE(profile);
216 ProfileStatistics* profile_stat =
217 ProfileStatisticsFactory::GetForProfile(profile);
218
219 scoped_refptr<content::MessageLoopRunner> loop1a =
lwchkg 2016/03/16 17:26:03 Using content::MessageLoopRunner instead of base::
Avi (use Gerrit) 2016/03/16 17:39:04 Offhand, no, I've never used so many at once. BTW
lwchkg 2016/03/16 18:36:41 content::MessageLoopRunner is a RefCounted, so we
220 new content::MessageLoopRunner;
221 scoped_refptr<content::MessageLoopRunner> loop1b =
222 new content::MessageLoopRunner;
223 scoped_refptr<content::MessageLoopRunner> loop2 =
224 new content::MessageLoopRunner;
225 ProfileStatisticsAggregatorState state1(loop1a->QuitClosure(), 1u);
226 ProfileStatisticsAggregatorState state2(loop2->QuitClosure());
227
228 EXPECT_FALSE(profile_stat->HasAggregator());
229 profile_stat->GatherStatistics(
230 base::Bind(&ProfileStatisticsAggregatorState::StatsCallback,
231 base::Unretained(&state1)));
232 ASSERT_TRUE(profile_stat->HasAggregator());
233 EXPECT_EQ(1u, profile_stat->GetAggregator()->GetCallbackCount());
234 loop1a->Run();
235
236 state1.SetQuitClosureAndRequiredStatCount(loop1b->QuitClosure(),
237 stats_categories().size());
238
239 profile_stat->GatherStatistics(
240 base::Bind(&ProfileStatisticsAggregatorState::StatsCallback,
241 base::Unretained(&state2)));
242 ASSERT_TRUE(profile_stat->HasAggregator());
243 EXPECT_EQ(2u, profile_stat->GetAggregator()->GetCallbackCount());
244 loop1b->Run();
245 loop2->Run();
246
247 EXPECT_EQ(0, state1.GetNumOfFails());
248
249 EXPECT_PRED_FORMAT2(AssertionProfileCategoryStatsEqual,
250 state1.GetStats(), state2.GetStats());
251 }
252
253 IN_PROC_BROWSER_TEST_F(ProfileStatisticsBrowserTest, CloseBrowser) {
254 Profile* profile = ProfileManager::GetActiveUserProfile();
255 ASSERT_TRUE(profile);
256 ProfileStatistics* profile_stat =
257 ProfileStatisticsFactory::GetForProfile(profile);
258
259 EXPECT_FALSE(profile_stat->HasAggregator());
260 CloseBrowserSynchronously(browser());
261 // The statistics task should be either running or finished.
262 if (profile_stat->HasAggregator()) {
263 EXPECT_EQ(0u, profile_stat->GetAggregator()->GetCallbackCount());
264 } else {
265 // Some of the statistics (e.g. settings) do always succeed. If all the
266 // statistics "failed", it means nothing is stored in profile attributes
267 // storage, and the statistics task was not run.
268 profiles::ProfileCategoryStats stats =
269 ProfileStatistics::GetProfileStatisticsFromCache(profile->GetPath());
270 bool has_stats = false;
271 for (const profiles::ProfileCategoryStat& stat : stats) {
272 if (stat.success) {
273 has_stats = true;
274 break;
275 }
276 }
277 EXPECT_TRUE(has_stats);
278 }
279 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698