domain_diversity_reporter_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. // Copyright 2019 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. #include "components/history/metrics/domain_diversity_reporter.h"
  5. #include "base/feature_list.h"
  6. #include "base/files/scoped_temp_dir.h"
  7. #include "base/test/bind.h"
  8. #include "base/test/metrics/histogram_tester.h"
  9. #include "base/test/task_environment.h"
  10. #include "base/time/clock.h"
  11. #include "base/time/time.h"
  12. #include "base/time/time_override.h"
  13. #include "components/history/core/browser/history_backend.h"
  14. #include "components/history/core/browser/history_database_params.h"
  15. #include "components/history/core/browser/history_service.h"
  16. #include "components/history/core/test/history_service_test_util.h"
  17. #include "components/history/core/test/test_history_database.h"
  18. #include "components/sync_preferences/testing_pref_service_syncable.h"
  19. #include "testing/gtest/include/gtest/gtest.h"
  20. namespace {
  21. // The interval between two scheduled computation tasks.
  22. constexpr base::TimeDelta kScheduleInterval = base::Days(1);
  23. // Pref name for the persistent timestamp of the last stats reporting.
  24. // Should be in sync with similar name in the reporter's impl.
  25. constexpr char kDomainDiversityReportingTimestamp[] =
  26. "domain_diversity.last_reporting_timestamp";
  27. } // namespace
  28. namespace history {
  29. class DomainDiversityReporterTest : public testing::Test {
  30. public:
  31. // TestClock uses a configurable time for testing.
  32. class TestClock : public base::Clock {
  33. public:
  34. explicit TestClock(base::Time time) : time_(time) {}
  35. base::Time Now() const override { return time_; }
  36. // Set the internal time.
  37. void SetTime(base::Time time) { time_ = time; }
  38. private:
  39. base::Time time_;
  40. };
  41. DomainDiversityReporterTest()
  42. : test_clock_(base::subtle::TimeNowIgnoringOverride()) {}
  43. DomainDiversityReporterTest(const DomainDiversityReporterTest&) = delete;
  44. DomainDiversityReporterTest& operator=(const DomainDiversityReporterTest&) =
  45. delete;
  46. ~DomainDiversityReporterTest() override = default;
  47. void SetUp() override {
  48. DomainDiversityReporter::RegisterProfilePrefs(pref_service_.registry());
  49. ASSERT_TRUE(history_dir_.CreateUniqueTempDir());
  50. // Creates HistoryService, but does not load it yet. Use LoadHistory() from
  51. // tests to control loading of HistoryService.
  52. history_service_ = std::make_unique<history::HistoryService>();
  53. // Sets the internal clock's current time to 10:00am. This avoids
  54. // issues in time arithmetic caused by uneven day lengths due to Daylight
  55. // Saving Time.
  56. test_clock_.SetTime(MidnightNDaysLater(test_clock_.Now(), 0) +
  57. base::Hours(10));
  58. }
  59. void CreateDomainDiversityReporter() {
  60. // The domain diversity reporter will schedule a domain computation task
  61. // immediately upon creation. Therefore, the reporter should be created
  62. // after the last reporting time has been properly set.
  63. reporter_ = std::make_unique<DomainDiversityReporter>(
  64. history_service(), &pref_service_, &test_clock_);
  65. }
  66. // Wait for separate background task runner in HistoryService to complete
  67. // all tasks and then all the tasks on the current one to complete as well.
  68. void Wait() {
  69. history::BlockUntilHistoryProcessesPendingRequests(history_service());
  70. }
  71. // Fast-forward some time before Wait.
  72. void FastForwardAndWait(base::TimeDelta time_delta) {
  73. task_environment_.FastForwardBy(time_delta);
  74. Wait();
  75. }
  76. bool LoadHistory() {
  77. if (!history_service_->Init(
  78. history::TestHistoryDatabaseParamsForPath(history_dir_.GetPath())))
  79. return false;
  80. history::BlockUntilHistoryProcessesPendingRequests(history_service());
  81. return true;
  82. }
  83. DomainDiversityReporter* reporter() const { return reporter_.get(); }
  84. const base::HistogramTester& histograms() const { return histogram_tester_; }
  85. history::HistoryService* history_service() { return history_service_.get(); }
  86. sync_preferences::TestingPrefServiceSyncable* prefs() {
  87. return &pref_service_;
  88. }
  89. TestClock& test_clock() { return test_clock_; }
  90. protected:
  91. // A `task_environment_` configured to MOCK_TIME so tests can
  92. // FastForwardAndWait() when waiting for a specific timeout (delayed task)
  93. // to fire. DomainDiversityReporter internally uses a `test_clock_` instead of
  94. // `task_environment_`'s clock because it needs to test very specific times
  95. // rather than just advance in deltas from Now().
  96. base::test::TaskEnvironment task_environment_{
  97. base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  98. std::unique_ptr<DomainDiversityReporter> reporter_;
  99. private:
  100. base::ScopedTempDir history_dir_;
  101. sync_preferences::TestingPrefServiceSyncable pref_service_;
  102. base::HistogramTester histogram_tester_;
  103. std::unique_ptr<history::HistoryService> history_service_;
  104. // The mock clock used by DomainDiversity internally.
  105. TestClock test_clock_;
  106. };
  107. TEST_F(DomainDiversityReporterTest, HistoryNotLoaded) {
  108. EXPECT_FALSE(history_service()->backend_loaded());
  109. CreateDomainDiversityReporter();
  110. task_environment_.RunUntilIdle();
  111. // Since History is not yet loaded, there should be no histograms.
  112. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 0);
  113. histograms().ExpectTotalCount("History.DomainCount1Day_V2", 0);
  114. histograms().ExpectTotalCount("History.DomainCount7Day_V2", 0);
  115. histograms().ExpectTotalCount("History.DomainCount28Day_V2", 0);
  116. // Load history. This should trigger reporter, via HistoryService observer.
  117. ASSERT_TRUE(LoadHistory());
  118. Wait();
  119. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 1);
  120. // No domains were visited, but there should be 7 samples. The last
  121. // reporting date, since it has never been set, was defaulted to epoch.
  122. histograms().ExpectUniqueSample("History.DomainCount1Day_V2", 0, 7);
  123. histograms().ExpectUniqueSample("History.DomainCount7Day_V2", 0, 7);
  124. histograms().ExpectUniqueSample("History.DomainCount28Day_V2", 0, 7);
  125. }
  126. TEST_F(DomainDiversityReporterTest, HistoryLoaded) {
  127. EXPECT_FALSE(history_service()->backend_loaded());
  128. ASSERT_TRUE(LoadHistory());
  129. // Set the last reporting date to 1 day ago.
  130. prefs()->SetTime(kDomainDiversityReportingTimestamp,
  131. MidnightNDaysLater(test_clock().Now(), -1));
  132. CreateDomainDiversityReporter();
  133. task_environment_.RunUntilIdle();
  134. // Since History is already loaded, there should be a sample reported.
  135. histograms().ExpectUniqueSample("History.DomainCount1Day_V2", 0, 1);
  136. histograms().ExpectUniqueSample("History.DomainCount7Day_V2", 0, 1);
  137. histograms().ExpectUniqueSample("History.DomainCount28Day_V2", 0, 1);
  138. }
  139. TEST_F(DomainDiversityReporterTest, HostAddedSimple) {
  140. ASSERT_TRUE(LoadHistory());
  141. // The last report was 3 days ago.
  142. prefs()->SetTime(kDomainDiversityReportingTimestamp,
  143. MidnightNDaysLater(test_clock().Now(), -3));
  144. // A domain was visited 2 days ago.
  145. base::Time two_days_ago = MidnightNDaysLater(test_clock().Now(), -2);
  146. history_service()->AddPage(GURL("http://www.google.com"), two_days_ago,
  147. history::VisitSource::SOURCE_BROWSED);
  148. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 0);
  149. CreateDomainDiversityReporter();
  150. task_environment_.RunUntilIdle();
  151. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 1);
  152. // There are 3 samples for each histogram. One sample of DomainCount1Day,
  153. // two samples of DomainCount7Day and two samples of DomainCount28Day
  154. // should have a visit count of 1.
  155. histograms().ExpectBucketCount("History.DomainCount1Day_V2", 1, 1);
  156. histograms().ExpectBucketCount("History.DomainCount1Day_V2", 0, 2);
  157. histograms().ExpectBucketCount("History.DomainCount7Day_V2", 1, 2);
  158. histograms().ExpectBucketCount("History.DomainCount7Day_V2", 0, 1);
  159. histograms().ExpectBucketCount("History.DomainCount28Day_V2", 1, 2);
  160. histograms().ExpectBucketCount("History.DomainCount28Day_V2", 0, 1);
  161. }
  162. TEST_F(DomainDiversityReporterTest, HostAddedLongAgo) {
  163. ASSERT_TRUE(LoadHistory());
  164. base::Time time_29_days_ago = MidnightNDaysLater(test_clock().Now(), -29);
  165. base::Time time_31_days_ago = MidnightNDaysLater(test_clock().Now(), -31);
  166. // The last report was 3 days ago.
  167. prefs()->SetTime(kDomainDiversityReportingTimestamp,
  168. MidnightNDaysLater(test_clock().Now(), -3));
  169. // The visit occurring on the same day as the reporting time
  170. // will not be counted.
  171. history_service()->AddPage(GURL("http://www.google.com"), test_clock().Now(),
  172. history::VisitSource::SOURCE_BROWSED);
  173. // Visits occurring 29 days ago will affect some DomainCount28Day
  174. // whose spanning period begins 29 days ago or earlier.
  175. history_service()->AddPage(GURL("http://example1.com"), time_29_days_ago,
  176. history::VisitSource::SOURCE_BROWSED);
  177. history_service()->AddPage(GURL("http://example2.com"), time_29_days_ago,
  178. history::VisitSource::SOURCE_BROWSED);
  179. history_service()->AddPage(GURL("http://example3.com"), time_29_days_ago,
  180. history::VisitSource::SOURCE_BROWSED);
  181. history_service()->AddPage(GURL("http://example4.com"), time_29_days_ago,
  182. history::VisitSource::SOURCE_BROWSED);
  183. // Visit occurring 31 days ago will not show in this report, since the earlier
  184. // spanning period in the test case begins 30 days ago.
  185. history_service()->AddPage(GURL("http://example.com"), time_31_days_ago,
  186. history::VisitSource::SOURCE_BROWSED);
  187. CreateDomainDiversityReporter();
  188. task_environment_.RunUntilIdle();
  189. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 1);
  190. histograms().ExpectUniqueSample("History.DomainCount1Day_V2", 0, 3);
  191. histograms().ExpectUniqueSample("History.DomainCount7Day_V2", 0, 3);
  192. // Two of the three DomainCount28Day samples should reflect the
  193. // 4 domain visits 29 days ago.
  194. histograms().ExpectBucketCount("History.DomainCount28Day_V2", 4, 2);
  195. histograms().ExpectBucketCount("History.DomainCount28Day_V2", 0, 1);
  196. }
  197. TEST_F(DomainDiversityReporterTest, ScheduleNextDay) {
  198. // Test if the next domain metrics reporting task is scheduled every 24 hours
  199. ASSERT_TRUE(LoadHistory());
  200. // Last report was emitted 4 days ago. So the report emitted today
  201. // will emit one set of histogram values of each of the last 4 days.
  202. prefs()->SetTime(kDomainDiversityReportingTimestamp,
  203. MidnightNDaysLater(test_clock().Now(), -4));
  204. history_service()->AddPage(GURL("http://www.google.com"),
  205. MidnightNDaysLater(test_clock().Now(), -2),
  206. history::VisitSource::SOURCE_BROWSED);
  207. history_service()->AddPage(GURL("http://www.example.com"),
  208. MidnightNDaysLater(test_clock().Now(), -2),
  209. history::VisitSource::SOURCE_BROWSED);
  210. // These visits are ignored in the initial DomainCount1Day values,
  211. // but will show in the one scheduled 24 hours later.
  212. history_service()->AddPage(GURL("http://www.example1.com"),
  213. test_clock().Now(),
  214. history::VisitSource::SOURCE_BROWSED);
  215. history_service()->AddPage(GURL("http://www.example2.com"),
  216. test_clock().Now(),
  217. history::VisitSource::SOURCE_BROWSED);
  218. history_service()->AddPage(GURL("http://www.example3.com"),
  219. test_clock().Now(),
  220. history::VisitSource::SOURCE_BROWSED);
  221. history_service()->AddPage(GURL("http://www.google.com"), test_clock().Now(),
  222. history::VisitSource::SOURCE_BROWSED);
  223. // These visits are included in the DomainCount7Day and DomainCount28Day
  224. // values of the first report, but will expire for the second report.
  225. history_service()->AddPage(GURL("http://www.visited-7-days-ago1.com"),
  226. MidnightNDaysLater(test_clock().Now(), -7),
  227. history::VisitSource::SOURCE_BROWSED);
  228. history_service()->AddPage(GURL("http://www.visited-28-days-ago.com"),
  229. MidnightNDaysLater(test_clock().Now(), -28),
  230. history::VisitSource::SOURCE_BROWSED);
  231. CreateDomainDiversityReporter();
  232. task_environment_.RunUntilIdle();
  233. // Two domains visited two days ago.
  234. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 1);
  235. histograms().ExpectBucketCount("History.DomainCount1Day_V2", 2, 1);
  236. histograms().ExpectBucketCount("History.DomainCount1Day_V2", 0, 3);
  237. histograms().ExpectBucketCount("History.DomainCount7Day_V2", 1, 2);
  238. histograms().ExpectBucketCount("History.DomainCount7Day_V2", 3, 2);
  239. histograms().ExpectBucketCount("History.DomainCount28Day_V2", 2, 2);
  240. histograms().ExpectBucketCount("History.DomainCount28Day_V2", 4, 2);
  241. test_clock().SetTime(MidnightNDaysLater(test_clock().Now(), 1) +
  242. base::Hours(10));
  243. FastForwardAndWait(kScheduleInterval); // fast-forward 24 hours
  244. // The new report will include the four domain visits on the last
  245. // repoting date.
  246. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 2);
  247. histograms().ExpectBucketCount("History.DomainCount1Day_V2", 4, 1);
  248. histograms().ExpectBucketCount("History.DomainCount1Day_V2", 2, 1);
  249. histograms().ExpectBucketCount("History.DomainCount1Day_V2", 0, 3);
  250. histograms().ExpectBucketCount("History.DomainCount7Day_V2", 5, 1);
  251. histograms().ExpectBucketCount("History.DomainCount7Day_V2", 1, 2);
  252. histograms().ExpectBucketCount("History.DomainCount7Day_V2", 3, 2);
  253. histograms().ExpectBucketCount("History.DomainCount28Day_V2", 6, 1);
  254. histograms().ExpectBucketCount("History.DomainCount28Day_V2", 2, 2);
  255. histograms().ExpectBucketCount("History.DomainCount28Day_V2", 4, 2);
  256. }
  257. TEST_F(DomainDiversityReporterTest, SaveTimestampInPreference) {
  258. ASSERT_TRUE(LoadHistory());
  259. base::Time last_midnight = MidnightNDaysLater(test_clock().Now(), -1);
  260. prefs()->SetTime(kDomainDiversityReportingTimestamp, last_midnight);
  261. EXPECT_EQ(last_midnight,
  262. prefs()->GetTime(kDomainDiversityReportingTimestamp));
  263. CreateDomainDiversityReporter();
  264. task_environment_.RunUntilIdle();
  265. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 1);
  266. // Reporter should have updated the pref to the time of the request.
  267. EXPECT_EQ(test_clock().Now(),
  268. prefs()->GetTime(kDomainDiversityReportingTimestamp));
  269. }
  270. TEST_F(DomainDiversityReporterTest, OnlyOneReportPerDay) {
  271. ASSERT_TRUE(LoadHistory());
  272. base::Time last_midnight = MidnightNDaysLater(test_clock().Now(), -1);
  273. prefs()->SetTime(kDomainDiversityReportingTimestamp, last_midnight);
  274. CreateDomainDiversityReporter();
  275. task_environment_.RunUntilIdle();
  276. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 1);
  277. histograms().ExpectUniqueSample("History.DomainCount1Day_V2", 0, 1);
  278. histograms().ExpectUniqueSample("History.DomainCount7Day_V2", 0, 1);
  279. histograms().ExpectUniqueSample("History.DomainCount28Day_V2", 0, 1);
  280. history_service()->AddPage(GURL("http://www.google.com"), test_clock().Now(),
  281. history::VisitSource::SOURCE_BROWSED);
  282. // Set the mock clock to 20:00 on the same day
  283. test_clock().SetTime(MidnightNDaysLater(test_clock().Now(), 0) +
  284. base::Hours(20));
  285. // Fast-forward the scheduler's clock by another 24 hours in order to trigger
  286. // the next report
  287. FastForwardAndWait(kScheduleInterval);
  288. // No new report since one report is already generated on the same day.
  289. // This could happen when the last report occurred very early
  290. // on a day longer than 24 hours (e.g. the day on which daylight saving
  291. // time ends).
  292. histograms().ExpectTotalCount("History.DomainCountQueryTime_V2", 1);
  293. histograms().ExpectUniqueSample("History.DomainCount1Day_V2", 0, 1);
  294. histograms().ExpectUniqueSample("History.DomainCount7Day_V2", 0, 1);
  295. histograms().ExpectUniqueSample("History.DomainCount28Day_V2", 0, 1);
  296. }
  297. } // namespace history