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 "chrome/browser/engagement/site_engagement_helper.h"
8 #include "chrome/browser/engagement/site_engagement_service.h"
9 #include "chrome/browser/engagement/site_engagement_service_factory.h"
10 #include "chrome/common/chrome_switches.h"
11 #include "chrome/test/base/browser_with_test_window_test.h"
12 #include "testing/gtest/include/gtest/gtest.h"
16 const int kLessNavigationsThanNeededToMaxDailyEngagement
= 2;
17 const int kMoreNavigationsThanNeededToMaxDailyEngagement
= 20;
18 const int kMoreNavigationsThanNeededToMaxTotalEngagement
= 200;
19 const int kLessDaysThanNeededToMaxTotalEngagement
= 4;
20 const int kMoreDaysThanNeededToMaxTotalEngagement
= 40;
21 const int kLessPeriodsThanNeededToDecayMaxScore
= 2;
22 const int kMorePeriodsThanNeededToDecayMaxScore
= 40;
24 base::Time
GetReferenceTime() {
25 base::Time::Exploded exploded_reference_time
;
26 exploded_reference_time
.year
= 2015;
27 exploded_reference_time
.month
= 1;
28 exploded_reference_time
.day_of_month
= 30;
29 exploded_reference_time
.day_of_week
= 5;
30 exploded_reference_time
.hour
= 11;
31 exploded_reference_time
.minute
= 0;
32 exploded_reference_time
.second
= 0;
33 exploded_reference_time
.millisecond
= 0;
35 return base::Time::FromLocalExploded(exploded_reference_time
);
40 class SiteEngagementScoreTest
: public testing::Test
{
42 SiteEngagementScoreTest() : score_(&test_clock_
) {}
45 base::SimpleTestClock test_clock_
;
46 SiteEngagementScore score_
;
49 // Navigate many times on the same day. Ensure each time the score goes up by
50 // kNavigationPoints, but not more than kMaxPointsPerDay.
51 TEST_F(SiteEngagementScoreTest
, NavigateOnSameDay
) {
52 base::Time reference_time
= GetReferenceTime();
54 test_clock_
.SetNow(reference_time
);
55 for (int i
= 0; i
< kMoreNavigationsThanNeededToMaxDailyEngagement
; ++i
) {
56 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
57 EXPECT_EQ(std::min(SiteEngagementScore::kMaxPointsPerDay
,
58 (i
+ 1) * SiteEngagementScore::kNavigationPoints
),
62 EXPECT_EQ(SiteEngagementScore::kMaxPointsPerDay
, score_
.Score());
65 // Navigate on the first day to max that day's engagement, then navigate on a
67 TEST_F(SiteEngagementScoreTest
, NavigateOnTwoDays
) {
68 base::Time reference_time
= GetReferenceTime();
69 base::Time later_date
= reference_time
+ base::TimeDelta::FromDays(2);
71 test_clock_
.SetNow(reference_time
);
72 for (int i
= 0; i
< kMoreNavigationsThanNeededToMaxDailyEngagement
; ++i
)
73 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
75 EXPECT_EQ(SiteEngagementScore::kMaxPointsPerDay
, score_
.Score());
77 test_clock_
.SetNow(later_date
);
78 for (int i
= 0; i
< kMoreNavigationsThanNeededToMaxDailyEngagement
; ++i
) {
79 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
81 std::min(SiteEngagementScore::kMaxPointsPerDay
,
82 (i
+ 1) * SiteEngagementScore::kNavigationPoints
);
83 EXPECT_EQ(day_score
+ SiteEngagementScore::kMaxPointsPerDay
,
87 EXPECT_EQ(2 * SiteEngagementScore::kMaxPointsPerDay
, score_
.Score());
90 // Navigate a lot on many consecutive days and ensure the score doesn't exceed
91 // the maximum allowed.
92 TEST_F(SiteEngagementScoreTest
, NavigateALotOnManyDays
) {
93 base::Time current_day
= GetReferenceTime();
95 for (int i
= 0; i
< kMoreDaysThanNeededToMaxTotalEngagement
; ++i
) {
96 current_day
+= base::TimeDelta::FromDays(1);
97 test_clock_
.SetNow(current_day
);
98 for (int j
= 0; j
< kMoreNavigationsThanNeededToMaxDailyEngagement
; ++j
)
99 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
101 EXPECT_EQ(std::min(SiteEngagementScore::kMaxPoints
,
102 (i
+ 1) * SiteEngagementScore::kMaxPointsPerDay
),
106 EXPECT_EQ(SiteEngagementScore::kMaxPoints
, score_
.Score());
109 // Navigate a little on many consecutive days and ensure the score doesn't
110 // exceed the maximum allowed.
111 TEST_F(SiteEngagementScoreTest
, NavigateALittleOnManyDays
) {
112 base::Time current_day
= GetReferenceTime();
114 for (int i
= 0; i
< kMoreNavigationsThanNeededToMaxTotalEngagement
; ++i
) {
115 current_day
+= base::TimeDelta::FromDays(1);
116 test_clock_
.SetNow(current_day
);
118 for (int j
= 0; j
< kLessNavigationsThanNeededToMaxDailyEngagement
; ++j
)
119 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
122 std::min(SiteEngagementScore::kMaxPoints
,
123 (i
+ 1) * kLessNavigationsThanNeededToMaxDailyEngagement
*
124 SiteEngagementScore::kNavigationPoints
),
128 EXPECT_EQ(SiteEngagementScore::kMaxPoints
, score_
.Score());
131 // Navigate a bit, then check the score decays properly for a range of times.
132 TEST_F(SiteEngagementScoreTest
, ScoresDecayOverTime
) {
133 base::Time current_day
= GetReferenceTime();
135 // First max the score.
136 for (int i
= 0; i
< kMoreDaysThanNeededToMaxTotalEngagement
; ++i
) {
137 current_day
+= base::TimeDelta::FromDays(1);
138 test_clock_
.SetNow(current_day
);
140 for (int j
= 0; j
< kMoreNavigationsThanNeededToMaxDailyEngagement
; ++j
)
141 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
144 EXPECT_EQ(SiteEngagementScore::kMaxPoints
, score_
.Score());
146 // The score should not have decayed before the first decay period has
150 base::TimeDelta::FromDays(SiteEngagementScore::kDecayPeriodInDays
- 1));
151 EXPECT_EQ(SiteEngagementScore::kMaxPoints
, score_
.Score());
153 // The score should have decayed by one chunk after one decay period has
157 base::TimeDelta::FromDays(SiteEngagementScore::kDecayPeriodInDays
));
158 EXPECT_EQ(SiteEngagementScore::kMaxPoints
- SiteEngagementScore::kDecayPoints
,
161 // The score should have decayed by the right number of chunks after a few
162 // decay periods have elapsed.
165 base::TimeDelta::FromDays(kLessPeriodsThanNeededToDecayMaxScore
*
166 SiteEngagementScore::kDecayPeriodInDays
));
167 EXPECT_EQ(SiteEngagementScore::kMaxPoints
-
168 kLessPeriodsThanNeededToDecayMaxScore
*
169 SiteEngagementScore::kDecayPoints
,
172 // The score should not decay below zero.
175 base::TimeDelta::FromDays(kMorePeriodsThanNeededToDecayMaxScore
*
176 SiteEngagementScore::kDecayPeriodInDays
));
177 EXPECT_EQ(0, score_
.Score());
180 // Test that any expected decays are applied before adding points.
181 TEST_F(SiteEngagementScoreTest
, DecaysAppliedBeforeAdd
) {
182 base::Time current_day
= GetReferenceTime();
184 // Get the score up to something that can handle a bit of decay before
185 for (int i
= 0; i
< kLessDaysThanNeededToMaxTotalEngagement
; ++i
) {
186 current_day
+= base::TimeDelta::FromDays(1);
187 test_clock_
.SetNow(current_day
);
189 for (int j
= 0; j
< kMoreNavigationsThanNeededToMaxDailyEngagement
; ++j
)
190 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
193 double initial_score
= kLessDaysThanNeededToMaxTotalEngagement
*
194 SiteEngagementScore::kMaxPointsPerDay
;
195 EXPECT_EQ(initial_score
, score_
.Score());
197 // Go forward a few decay periods.
200 base::TimeDelta::FromDays(kLessPeriodsThanNeededToDecayMaxScore
*
201 SiteEngagementScore::kDecayPeriodInDays
));
203 double decayed_score
=
205 kLessPeriodsThanNeededToDecayMaxScore
* SiteEngagementScore::kDecayPoints
;
206 EXPECT_EQ(decayed_score
, score_
.Score());
208 // Now add some points.
209 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
210 EXPECT_EQ(decayed_score
+ SiteEngagementScore::kNavigationPoints
,
214 // Test that going back in time is handled properly.
215 TEST_F(SiteEngagementScoreTest
, GoBackInTime
) {
216 base::Time current_day
= GetReferenceTime();
218 test_clock_
.SetNow(current_day
);
219 for (int i
= 0; i
< kMoreNavigationsThanNeededToMaxDailyEngagement
; ++i
)
220 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
222 EXPECT_EQ(SiteEngagementScore::kMaxPointsPerDay
, score_
.Score());
224 // Adding to the score on an earlier date should be treated like another day,
225 // and should not cause any decay.
226 test_clock_
.SetNow(current_day
- base::TimeDelta::FromDays(
227 kMorePeriodsThanNeededToDecayMaxScore
*
228 SiteEngagementScore::kDecayPoints
));
229 for (int i
= 0; i
< kMoreNavigationsThanNeededToMaxDailyEngagement
; ++i
) {
230 score_
.AddPoints(SiteEngagementScore::kNavigationPoints
);
232 std::min(SiteEngagementScore::kMaxPointsPerDay
,
233 (i
+ 1) * SiteEngagementScore::kNavigationPoints
);
234 EXPECT_EQ(day_score
+ SiteEngagementScore::kMaxPointsPerDay
,
238 EXPECT_EQ(2 * SiteEngagementScore::kMaxPointsPerDay
, score_
.Score());
241 using SiteEngagementServiceTest
= BrowserWithTestWindowTest
;
243 // Tests that the Site Engagement service is hooked up properly to navigations
244 // by performing two navigations and checking the engagement score increases
246 TEST_F(SiteEngagementServiceTest
, ScoreIncrementsOnPageRequest
) {
247 base::CommandLine::ForCurrentProcess()->AppendSwitch(
248 switches::kEnableSiteEngagementService
);
250 SiteEngagementService
* service
=
251 SiteEngagementServiceFactory::GetForProfile(profile());
254 GURL
url("http://www.google.com/");
256 AddTab(browser(), GURL("about:blank"));
257 EXPECT_EQ(0, service
->GetScore(url
));
258 int prev_score
= service
->GetScore(url
);
260 NavigateAndCommitActiveTab(url
);
261 EXPECT_LT(prev_score
, service
->GetScore(url
));
262 prev_score
= service
->GetScore(url
);
264 NavigateAndCommitActiveTab(url
);
265 EXPECT_LT(prev_score
, service
->GetScore(url
));