15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/visit_filter.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/history/core/browser/history_types.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// So the tests won't go into the other day +/- several hours, return midday of
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// today.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Time GetClosestMidday() {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::Time::Now().LocalMidnight() + base::TimeDelta::FromHours(12);
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VisitFilterTest : public testing::Test {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilterTest();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp();
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VisitFilterTest::VisitFilterTest() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitFilterTest::SetUp() {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitFilterTest::TearDown() {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitFilterTest, CheckFilters) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time t(GetClosestMidday());
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta two_hours(base::TimeDelta::FromHours(2));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter f;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  f.set_max_results(21U);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  f.SetFilterTime(t);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  f.SetFilterWidth(two_hours);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(21U, f.times().size());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < f.times().size(); ++i) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time t_interval(t);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t_interval -= base::TimeDelta::FromDays(i);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(t_interval - two_hours, f.times()[i].first) <<
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Fails at index:" << i;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(t_interval + two_hours, f.times()[i].second) <<
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Fails at index:" << i;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time::Exploded et;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.LocalExplode(&et);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  f.SetDayOfTheWeekFilter(et.day_of_week);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3 weeks in 21 days.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(3U, f.times().size());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 1; i < f.times().size(); ++i) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time t_interval(t);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t_interval -= base::TimeDelta::FromDays(i);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(f.times()[i].first + base::TimeDelta::FromDays(7),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              f.times()[i - 1].first) <<
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Fails at index:" << i;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(f.times()[i].second + base::TimeDelta::FromDays(7),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              f.times()[i - 1].second) <<
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Fails at index:" << i;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(two_hours * 2,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              f.times()[i].second - f.times()[i].first) <<
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Fails at index:" << i;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitFilterTest, GetTimesInRange) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time::Exploded et = { 2011, 7, 0, 19, 22, 15, 11, 0 };
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time t(base::Time::FromLocalExploded(et));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta two_hours(base::TimeDelta::FromHours(2));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::TimeVector times;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::GetTimesInRange(t - two_hours, t + two_hours, 10U, &times);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(11U, times.size());
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < times.size(); ++i) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time t_interval(t);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t_interval -= base::TimeDelta::FromDays(i);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(t_interval - two_hours, times[i].first) << "Fails at index:" << i;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(t_interval + two_hours, times[i].second) <<
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Fails at index:" << i;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitFilterTest, GetTimesOnTheDayOfTheWeek) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time t(GetClosestMidday());
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::TimeVector times;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time::Exploded et;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.LocalExplode(&et);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::GetTimesOnTheDayOfTheWeek(et.day_of_week, t, 10U, &times);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(11U, times.size());
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  et.hour = 0;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  et.minute = 0;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  et.second = 0;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  et.millisecond = 0;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < times.size(); ++i) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time t_interval(base::Time::FromLocalExploded(et));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t_interval -= base::TimeDelta::FromDays(7 * i);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(t_interval, times[i].first) << "Fails at index:" << i;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(t_interval + base::TimeDelta::FromDays(1), times[i].second) <<
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Fails at index:" << i;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitFilterTest, GetTimesOnTheSameDayType) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time::Exploded et = { 2011, 7, 0, 19, 22, 15, 11, 0 };
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time t(base::Time::FromLocalExploded(et));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::TimeVector times;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.LocalExplode(&et);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::GetTimesOnTheSameDayType(et.day_of_week, t, 10U, &times);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(11U, times.size());
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  et.hour = 0;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  et.minute = 0;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  et.second = 0;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  et.millisecond = 0;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time t_start(base::Time::FromLocalExploded(et));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta t_length;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (et.day_of_week == 0 || et.day_of_week == 6) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sunday and Saturday.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t_length = base::TimeDelta::FromDays(2);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (et.day_of_week == 0)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      t_start -= base::TimeDelta::FromDays(1);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t_length = base::TimeDelta::FromDays(5);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (et.day_of_week != 1)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      t_start -= base::TimeDelta::FromDays(et.day_of_week - 1);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < times.size(); ++i) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time t_interval(t_start);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t_interval -= base::TimeDelta::FromDays(7 * i);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(t_interval, times[i].first) << "Fails at index:" << i;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(t_interval + t_length, times[i].second) << "Fails at index:" << i;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitFilterTest, UniteTimeVectors) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time t(base::Time::Now());
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta one_hour(base::TimeDelta::FromHours(1));
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta one_day(base::TimeDelta::FromDays(1));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::TimeVector times1;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.push_back(std::make_pair(t - one_hour, t + one_hour));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.push_back(std::make_pair(t - one_hour - one_day,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour - one_day));
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.push_back(std::make_pair(t - one_hour - one_day * 2,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour - one_day * 2));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.push_back(std::make_pair(t - one_hour - one_day * 3,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour - one_day * 3));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::TimeVector times2;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should lie completely within times1[0].
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.push_back(std::make_pair(t - one_hour / 2, t + one_hour / 2));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should lie just before times1[1].
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.push_back(std::make_pair(t + one_hour * 2 - one_day,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour * 3 - one_day));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should intersect with times1.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.push_back(std::make_pair(t - one_day * 2,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour * 2 - one_day * 2));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.push_back(std::make_pair(t - one_hour * 2 - one_day * 3,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t - one_day * 3));
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::TimeVector result;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(VisitFilter::UniteTimeVectors(times1, times2, &result));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(5U, result.size());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t - one_hour, result[0].first);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t + one_hour, result[0].second);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t + one_hour * 2 - one_day, result[1].first);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t + one_hour * 3 - one_day, result[1].second);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t - one_hour - one_day, result[2].first);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t + one_hour - one_day, result[2].second);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t - one_hour - one_day * 2, result[3].first);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t + one_hour * 2 - one_day * 2, result[3].second);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t - one_hour * 2 - one_day * 3, result[4].first);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t + one_hour - one_day * 3, result[4].second);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(VisitFilter::UniteTimeVectors(VisitFilter::TimeVector(),
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             VisitFilter::TimeVector(),
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             &result));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(result.empty());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitFilterTest, IntersectTimeVectors) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time t(base::Time::Now());
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta one_hour(base::TimeDelta::FromHours(1));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta one_day(base::TimeDelta::FromDays(1));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::TimeVector times1;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.push_back(std::make_pair(t - one_hour, t + one_hour));
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::TimeVector times2;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should lie just before times1[0].
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.push_back(std::make_pair(t + one_hour * 2,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour * 3));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter::TimeVector result;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(VisitFilter::IntersectTimeVectors(times1, times2, &result));
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(result.empty());
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.push_back(std::make_pair(t - one_hour - one_day,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour - one_day));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.push_back(std::make_pair(t - one_hour - one_day * 2,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour - one_day * 2));
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.push_back(std::make_pair(t - one_hour - one_day * 3,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour - one_day * 3));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should lie completely within times1[1].
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.push_back(std::make_pair(t - one_hour / 2 - one_day,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour / 2 - one_day));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should intersect with times1.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.push_back(std::make_pair(t - one_day * 2,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t + one_hour * 2 - one_day * 2));
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.push_back(std::make_pair(t - one_hour * 2 - one_day * 3,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  t - one_day * 3));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(VisitFilter::IntersectTimeVectors(times1, times2, &result));
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(3U, result.size());
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t - one_hour / 2 - one_day, result[0].first);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t + one_hour / 2 - one_day, result[0].second);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t - one_day * 2, result[1].first);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t + one_hour - one_day * 2, result[1].second);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t - one_hour - one_day * 3, result[2].first);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(t - one_day * 3, result[2].second);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that touching ranges do not intersect.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.clear();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times1.push_back(std::make_pair(t - one_hour, t));
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.clear();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  times2.push_back(std::make_pair(t, t + one_hour));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(VisitFilter::IntersectTimeVectors(times1, times2, &result));
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(result.empty());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitFilterTest, GetVisitScore) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time filter_time;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(base::Time::FromString("Tue, 24 Apr 2012, 12:00:00",
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &filter_time));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitFilter filter;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitRow visit;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter.set_sorting_order(VisitFilter::ORDER_BY_RECENCY);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter.SetFilterTime(filter_time);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter.SetFilterWidth(base::TimeDelta::FromHours(1));
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double one_week_one_hour_staleness = pow(2, -(24.0 * 7.0 + 1.0) /
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               (24.0 * 7.0));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No decay on current visit.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(1.0, filter.GetVisitScore(visit));
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Half score after a week.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time - base::TimeDelta::FromDays(7);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(0.5, filter.GetVisitScore(visit));
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Future visits should be treated as current.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time + base::TimeDelta::FromDays(1);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(1.0, filter.GetVisitScore(visit));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter.set_sorting_order(VisitFilter::ORDER_BY_VISIT_COUNT);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Every visit should score 1 with this filter.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(1.0, filter.GetVisitScore(visit));
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time - base::TimeDelta::FromDays(7);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(1.0, filter.GetVisitScore(visit));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time + base::TimeDelta::FromDays(7);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(1.0, filter.GetVisitScore(visit));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter.set_sorting_order(VisitFilter::ORDER_BY_TIME_LINEAR);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(1.0, filter.GetVisitScore(visit));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Half the filter width forward in time should get half the score for the
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // time difference, but no staleness decay.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time + base::TimeDelta::FromMinutes(30);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(0.5, filter.GetVisitScore(visit));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One week back in time gets full time difference score, but a staleness
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // factor of 0.5
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time - base::TimeDelta::FromDays(7);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(0.5, filter.GetVisitScore(visit));
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One week plus half a filter width should have it's score halved before
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the staleness factor.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter.SetFilterWidth(base::TimeDelta::FromHours(2));
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time - base::TimeDelta::FromDays(7) -
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::TimeDelta::FromHours(1);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(0.5 * one_week_one_hour_staleness,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   filter.GetVisitScore(visit));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter.SetFilterWidth(base::TimeDelta::FromHours(1));
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter.set_sorting_order(VisitFilter::ORDER_BY_TIME_GAUSSIAN);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(1.0, filter.GetVisitScore(visit));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Going forward in time to test the normal distribution function.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time + base::TimeDelta::FromHours(1);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(exp(-0.5), filter.GetVisitScore(visit));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time + base::TimeDelta::FromMinutes(30);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(exp(-0.125), filter.GetVisitScore(visit));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One week back in time gets full time difference score, but a staleness
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // factor of 0.5
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time - base::TimeDelta::FromDays(7);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(0.5, filter.GetVisitScore(visit));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // One standard deviation of decay, plus the staleness factor.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visit.visit_time = filter_time - base::TimeDelta::FromDays(7) -
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::TimeDelta::FromHours(1);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_DOUBLE_EQ(exp(-0.5) * one_week_one_hour_staleness,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   filter.GetVisitScore(visit));
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace history
315