Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / engagement / site_engagement_service_unittest.cc
blobadff26216ee58491a3dc25391c426685b88f9148
1 // Copyright 2015 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.
5 #include "base/command_line.h"
6 #include "base/test/simple_test_clock.h"
7 #include "base/values.h"
8 #include "chrome/browser/engagement/site_engagement_helper.h"
9 #include "chrome/browser/engagement/site_engagement_service.h"
10 #include "chrome/browser/engagement/site_engagement_service_factory.h"
11 #include "chrome/common/chrome_switches.h"
12 #include "chrome/test/base/browser_with_test_window_test.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace {
17 const int kLessNavigationsThanNeededToMaxDailyEngagement = 2;
18 const int kMoreNavigationsThanNeededToMaxDailyEngagement = 20;
19 const int kMoreNavigationsThanNeededToMaxTotalEngagement = 200;
20 const int kLessDaysThanNeededToMaxTotalEngagement = 4;
21 const int kMoreDaysThanNeededToMaxTotalEngagement = 40;
22 const int kLessPeriodsThanNeededToDecayMaxScore = 2;
23 const int kMorePeriodsThanNeededToDecayMaxScore = 40;
25 base::Time GetReferenceTime() {
26 base::Time::Exploded exploded_reference_time;
27 exploded_reference_time.year = 2015;
28 exploded_reference_time.month = 1;
29 exploded_reference_time.day_of_month = 30;
30 exploded_reference_time.day_of_week = 5;
31 exploded_reference_time.hour = 11;
32 exploded_reference_time.minute = 0;
33 exploded_reference_time.second = 0;
34 exploded_reference_time.millisecond = 0;
36 return base::Time::FromLocalExploded(exploded_reference_time);
39 } // namespace
41 class SiteEngagementScoreTest : public testing::Test {
42 public:
43 SiteEngagementScoreTest() : score_(&test_clock_) {}
45 protected:
46 void VerifyScore(const SiteEngagementScore& score,
47 double expected_raw_score,
48 double expected_points_added_today,
49 base::Time expected_last_engagement_time) {
50 EXPECT_EQ(expected_raw_score, score.raw_score_);
51 EXPECT_EQ(expected_points_added_today, score.points_added_today_);
52 EXPECT_EQ(expected_last_engagement_time, score.last_engagement_time_);
55 void UpdateScore(SiteEngagementScore* score,
56 double raw_score,
57 double points_added_today,
58 base::Time last_engagement_time) {
59 score->raw_score_ = raw_score;
60 score->points_added_today_ = points_added_today;
61 score->last_engagement_time_ = last_engagement_time;
64 void TestScoreInitializesAndUpdates(
65 base::DictionaryValue* score_dict,
66 double expected_raw_score,
67 double expected_points_added_today,
68 base::Time expected_last_engagement_time) {
69 SiteEngagementScore initial_score(&test_clock_, *score_dict);
70 VerifyScore(initial_score, expected_raw_score, expected_points_added_today,
71 expected_last_engagement_time);
73 // Updating the score dict should return false, as the score shouldn't
74 // have changed at this point.
75 EXPECT_FALSE(initial_score.UpdateScoreDict(score_dict));
77 // Update the score to new values and verify it updates the score dict
78 // correctly.
79 base::Time different_day =
80 GetReferenceTime() + base::TimeDelta::FromDays(1);
81 UpdateScore(&initial_score, 5, 10, different_day);
82 EXPECT_TRUE(initial_score.UpdateScoreDict(score_dict));
83 SiteEngagementScore updated_score(&test_clock_, *score_dict);
84 VerifyScore(updated_score, 5, 10, different_day);
87 base::SimpleTestClock test_clock_;
88 SiteEngagementScore score_;
91 // Navigate many times on the same day. Ensure each time the score goes up by
92 // kNavigationPoints, but not more than kMaxPointsPerDay.
93 TEST_F(SiteEngagementScoreTest, NavigateOnSameDay) {
94 base::Time reference_time = GetReferenceTime();
96 test_clock_.SetNow(reference_time);
97 for (int i = 0; i < kMoreNavigationsThanNeededToMaxDailyEngagement; ++i) {
98 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
99 EXPECT_EQ(std::min(SiteEngagementScore::kMaxPointsPerDay,
100 (i + 1) * SiteEngagementScore::kNavigationPoints),
101 score_.Score());
104 EXPECT_EQ(SiteEngagementScore::kMaxPointsPerDay, score_.Score());
107 // Navigate on the first day to max that day's engagement, then navigate on a
108 // different day.
109 TEST_F(SiteEngagementScoreTest, NavigateOnTwoDays) {
110 base::Time reference_time = GetReferenceTime();
111 base::Time later_date = reference_time + base::TimeDelta::FromDays(2);
113 test_clock_.SetNow(reference_time);
114 for (int i = 0; i < kMoreNavigationsThanNeededToMaxDailyEngagement; ++i)
115 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
117 EXPECT_EQ(SiteEngagementScore::kMaxPointsPerDay, score_.Score());
119 test_clock_.SetNow(later_date);
120 for (int i = 0; i < kMoreNavigationsThanNeededToMaxDailyEngagement; ++i) {
121 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
122 double day_score =
123 std::min(SiteEngagementScore::kMaxPointsPerDay,
124 (i + 1) * SiteEngagementScore::kNavigationPoints);
125 EXPECT_EQ(day_score + SiteEngagementScore::kMaxPointsPerDay,
126 score_.Score());
129 EXPECT_EQ(2 * SiteEngagementScore::kMaxPointsPerDay, score_.Score());
132 // Navigate a lot on many consecutive days and ensure the score doesn't exceed
133 // the maximum allowed.
134 TEST_F(SiteEngagementScoreTest, NavigateALotOnManyDays) {
135 base::Time current_day = GetReferenceTime();
137 for (int i = 0; i < kMoreDaysThanNeededToMaxTotalEngagement; ++i) {
138 current_day += base::TimeDelta::FromDays(1);
139 test_clock_.SetNow(current_day);
140 for (int j = 0; j < kMoreNavigationsThanNeededToMaxDailyEngagement; ++j)
141 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
143 EXPECT_EQ(std::min(SiteEngagementScore::kMaxPoints,
144 (i + 1) * SiteEngagementScore::kMaxPointsPerDay),
145 score_.Score());
148 EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.Score());
151 // Navigate a little on many consecutive days and ensure the score doesn't
152 // exceed the maximum allowed.
153 TEST_F(SiteEngagementScoreTest, NavigateALittleOnManyDays) {
154 base::Time current_day = GetReferenceTime();
156 for (int i = 0; i < kMoreNavigationsThanNeededToMaxTotalEngagement; ++i) {
157 current_day += base::TimeDelta::FromDays(1);
158 test_clock_.SetNow(current_day);
160 for (int j = 0; j < kLessNavigationsThanNeededToMaxDailyEngagement; ++j)
161 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
163 EXPECT_EQ(
164 std::min(SiteEngagementScore::kMaxPoints,
165 (i + 1) * kLessNavigationsThanNeededToMaxDailyEngagement *
166 SiteEngagementScore::kNavigationPoints),
167 score_.Score());
170 EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.Score());
173 // Navigate a bit, then check the score decays properly for a range of times.
174 TEST_F(SiteEngagementScoreTest, ScoresDecayOverTime) {
175 base::Time current_day = GetReferenceTime();
177 // First max the score.
178 for (int i = 0; i < kMoreDaysThanNeededToMaxTotalEngagement; ++i) {
179 current_day += base::TimeDelta::FromDays(1);
180 test_clock_.SetNow(current_day);
182 for (int j = 0; j < kMoreNavigationsThanNeededToMaxDailyEngagement; ++j)
183 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
186 EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.Score());
188 // The score should not have decayed before the first decay period has
189 // elapsed.
190 test_clock_.SetNow(
191 current_day +
192 base::TimeDelta::FromDays(SiteEngagementScore::kDecayPeriodInDays - 1));
193 EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.Score());
195 // The score should have decayed by one chunk after one decay period has
196 // elapsed.
197 test_clock_.SetNow(
198 current_day +
199 base::TimeDelta::FromDays(SiteEngagementScore::kDecayPeriodInDays));
200 EXPECT_EQ(SiteEngagementScore::kMaxPoints - SiteEngagementScore::kDecayPoints,
201 score_.Score());
203 // The score should have decayed by the right number of chunks after a few
204 // decay periods have elapsed.
205 test_clock_.SetNow(
206 current_day +
207 base::TimeDelta::FromDays(kLessPeriodsThanNeededToDecayMaxScore *
208 SiteEngagementScore::kDecayPeriodInDays));
209 EXPECT_EQ(SiteEngagementScore::kMaxPoints -
210 kLessPeriodsThanNeededToDecayMaxScore *
211 SiteEngagementScore::kDecayPoints,
212 score_.Score());
214 // The score should not decay below zero.
215 test_clock_.SetNow(
216 current_day +
217 base::TimeDelta::FromDays(kMorePeriodsThanNeededToDecayMaxScore *
218 SiteEngagementScore::kDecayPeriodInDays));
219 EXPECT_EQ(0, score_.Score());
222 // Test that any expected decays are applied before adding points.
223 TEST_F(SiteEngagementScoreTest, DecaysAppliedBeforeAdd) {
224 base::Time current_day = GetReferenceTime();
226 // Get the score up to something that can handle a bit of decay before
227 for (int i = 0; i < kLessDaysThanNeededToMaxTotalEngagement; ++i) {
228 current_day += base::TimeDelta::FromDays(1);
229 test_clock_.SetNow(current_day);
231 for (int j = 0; j < kMoreNavigationsThanNeededToMaxDailyEngagement; ++j)
232 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
235 double initial_score = kLessDaysThanNeededToMaxTotalEngagement *
236 SiteEngagementScore::kMaxPointsPerDay;
237 EXPECT_EQ(initial_score, score_.Score());
239 // Go forward a few decay periods.
240 test_clock_.SetNow(
241 current_day +
242 base::TimeDelta::FromDays(kLessPeriodsThanNeededToDecayMaxScore *
243 SiteEngagementScore::kDecayPeriodInDays));
245 double decayed_score =
246 initial_score -
247 kLessPeriodsThanNeededToDecayMaxScore * SiteEngagementScore::kDecayPoints;
248 EXPECT_EQ(decayed_score, score_.Score());
250 // Now add some points.
251 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
252 EXPECT_EQ(decayed_score + SiteEngagementScore::kNavigationPoints,
253 score_.Score());
256 // Test that going back in time is handled properly.
257 TEST_F(SiteEngagementScoreTest, GoBackInTime) {
258 base::Time current_day = GetReferenceTime();
260 test_clock_.SetNow(current_day);
261 for (int i = 0; i < kMoreNavigationsThanNeededToMaxDailyEngagement; ++i)
262 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
264 EXPECT_EQ(SiteEngagementScore::kMaxPointsPerDay, score_.Score());
266 // Adding to the score on an earlier date should be treated like another day,
267 // and should not cause any decay.
268 test_clock_.SetNow(current_day - base::TimeDelta::FromDays(
269 kMorePeriodsThanNeededToDecayMaxScore *
270 SiteEngagementScore::kDecayPoints));
271 for (int i = 0; i < kMoreNavigationsThanNeededToMaxDailyEngagement; ++i) {
272 score_.AddPoints(SiteEngagementScore::kNavigationPoints);
273 double day_score =
274 std::min(SiteEngagementScore::kMaxPointsPerDay,
275 (i + 1) * SiteEngagementScore::kNavigationPoints);
276 EXPECT_EQ(day_score + SiteEngagementScore::kMaxPointsPerDay,
277 score_.Score());
280 EXPECT_EQ(2 * SiteEngagementScore::kMaxPointsPerDay, score_.Score());
283 // Test that scores are read / written correctly from / to empty score
284 // dictionaries.
285 TEST_F(SiteEngagementScoreTest, EmptyDictionary) {
286 base::DictionaryValue dict;
287 TestScoreInitializesAndUpdates(&dict, 0, 0, base::Time());
290 // Test that scores are read / written correctly from / to partially empty
291 // score dictionaries.
292 TEST_F(SiteEngagementScoreTest, PartiallyEmptyDictionary) {
293 base::DictionaryValue dict;
294 dict.SetDouble(SiteEngagementScore::kPointsAddedTodayKey, 2);
296 TestScoreInitializesAndUpdates(&dict, 0, 2, base::Time());
299 // Test that scores are read / written correctly from / to populated score
300 // dictionaries.
301 TEST_F(SiteEngagementScoreTest, PopulatedDictionary) {
302 base::DictionaryValue dict;
303 dict.SetDouble(SiteEngagementScore::kRawScoreKey, 1);
304 dict.SetDouble(SiteEngagementScore::kPointsAddedTodayKey, 2);
305 dict.SetDouble(SiteEngagementScore::kLastEngagementTimeKey,
306 GetReferenceTime().ToInternalValue());
308 TestScoreInitializesAndUpdates(&dict, 1, 2, GetReferenceTime());
312 class SiteEngagementServiceTest : public BrowserWithTestWindowTest {
313 public:
314 SiteEngagementServiceTest() {}
316 void SetUp() override {
317 BrowserWithTestWindowTest::SetUp();
318 base::CommandLine::ForCurrentProcess()->AppendSwitch(
319 switches::kEnableSiteEngagementService);
324 // Tests that the Site Engagement service is hooked up properly to navigations
325 // by performing two navigations and checking the engagement score increases
326 // both times.
327 TEST_F(SiteEngagementServiceTest, ScoreIncrementsOnPageRequest) {
328 SiteEngagementService* service =
329 SiteEngagementServiceFactory::GetForProfile(profile());
330 DCHECK(service);
332 GURL url("http://www.google.com/");
334 AddTab(browser(), GURL("about:blank"));
335 EXPECT_EQ(0, service->GetScore(url));
336 int prev_score = service->GetScore(url);
338 NavigateAndCommitActiveTab(url);
339 EXPECT_LT(prev_score, service->GetScore(url));
340 prev_score = service->GetScore(url);
342 NavigateAndCommitActiveTab(url);
343 EXPECT_LT(prev_score, service->GetScore(url));
346 // Expect that site engagement scores for several sites are correctly aggregated
347 // by GetTotalEngagementPoints().
348 TEST_F(SiteEngagementServiceTest, GetTotalEngagementPoints) {
349 SiteEngagementService* service =
350 SiteEngagementServiceFactory::GetForProfile(profile());
351 DCHECK(service);
353 // The https and http versions of www.google.com should be separate.
354 GURL url1("https://www.google.com/");
355 GURL url2("http://www.google.com/");
356 GURL url3("http://drive.google.com/");
358 EXPECT_EQ(0, service->GetScore(url1));
359 EXPECT_EQ(0, service->GetScore(url2));
360 EXPECT_EQ(0, service->GetScore(url3));
362 service->HandleNavigation(url1);
363 EXPECT_EQ(1, service->GetScore(url1));
364 EXPECT_EQ(1, service->GetTotalEngagementPoints());
366 service->HandleNavigation(url2);
367 service->HandleNavigation(url2);
368 EXPECT_EQ(2, service->GetScore(url2));
369 EXPECT_EQ(3, service->GetTotalEngagementPoints());
371 service->HandleNavigation(url3);
372 EXPECT_EQ(1, service->GetScore(url3));
373 EXPECT_EQ(4, service->GetTotalEngagementPoints());
375 service->HandleNavigation(url1);
376 service->HandleNavigation(url1);
377 EXPECT_EQ(3, service->GetScore(url1));
378 EXPECT_EQ(6, service->GetTotalEngagementPoints());