1// Copyright 2014 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 "components/suggestions/suggestions_store.h"
6
7#include "base/time/time.h"
8#include "components/pref_registry/testing_pref_service_syncable.h"
9#include "components/suggestions/proto/suggestions.pb.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12using user_prefs::TestingPrefServiceSyncable;
13
14namespace suggestions {
15
16namespace {
17
18const char kTestTitle[] = "Foo site";
19const char kTestUrl[] = "http://foo.com/";
20const int kTimeGapUsec = 100000;
21
22void AddSuggestion(SuggestionsProfile* suggestions, const char *title,
23                   const char *url, int64 expiry_ts) {
24  ChromeSuggestion* suggestion = suggestions->add_suggestions();
25  suggestion->set_url(title);
26  suggestion->set_title(url);
27  suggestion->set_expiry_ts(expiry_ts);
28}
29
30SuggestionsProfile CreateTestSuggestions() {
31  SuggestionsProfile suggestions;
32  ChromeSuggestion* suggestion = suggestions.add_suggestions();
33  suggestion->set_url(kTestTitle);
34  suggestion->set_title(kTestUrl);
35  return suggestions;
36}
37
38SuggestionsProfile CreateTestSuggestionsProfileWithExpiry(int expired_count,
39                                                          int valid_count) {
40  int64 now_usec = (base::Time::NowFromSystemTime() - base::Time::UnixEpoch())
41      .ToInternalValue();
42  srand(7);  // Constant seed for rand() function.
43  int64 offset_limit_usec = 30 * base::Time::kMicrosecondsPerDay;
44  int64 offset_usec = rand() % offset_limit_usec + kTimeGapUsec;
45
46  SuggestionsProfile suggestions;
47  for (int i = 0; i < valid_count; i++)
48    AddSuggestion(&suggestions, kTestTitle, kTestUrl, now_usec + offset_usec);
49  for (int i = 0; i < expired_count; i++)
50    AddSuggestion(&suggestions, kTestTitle, kTestUrl, now_usec - offset_usec);
51
52  return suggestions;
53}
54
55void ValidateSuggestions(const SuggestionsProfile& expected,
56                         const SuggestionsProfile& actual) {
57  EXPECT_EQ(expected.suggestions_size(), actual.suggestions_size());
58  for (int i = 0; i < expected.suggestions_size(); ++i) {
59    EXPECT_EQ(expected.suggestions(i).url(), actual.suggestions(i).url());
60    EXPECT_EQ(expected.suggestions(i).title(), actual.suggestions(i).title());
61    EXPECT_EQ(expected.suggestions(i).expiry_ts(),
62              actual.suggestions(i).expiry_ts());
63    EXPECT_EQ(expected.suggestions(i).favicon_url(),
64              actual.suggestions(i).favicon_url());
65    EXPECT_EQ(expected.suggestions(i).thumbnail(),
66              actual.suggestions(i).thumbnail());
67  }
68}
69
70}  // namespace
71
72class SuggestionsStoreTest : public testing::Test {
73 public:
74  SuggestionsStoreTest()
75    : pref_service_(new user_prefs::TestingPrefServiceSyncable) {}
76
77  virtual void SetUp() OVERRIDE {
78    SuggestionsStore::RegisterProfilePrefs(pref_service_->registry());
79    suggestions_store_.reset(new SuggestionsStore(pref_service_.get()));
80  }
81
82 protected:
83  scoped_ptr<user_prefs::TestingPrefServiceSyncable> pref_service_;
84  scoped_ptr<SuggestionsStore> suggestions_store_;
85
86  DISALLOW_COPY_AND_ASSIGN(SuggestionsStoreTest);
87};
88
89// Tests LoadSuggestions function to filter expired suggestions.
90TEST_F(SuggestionsStoreTest, LoadAllExpired) {
91  SuggestionsProfile suggestions = CreateTestSuggestionsProfileWithExpiry(5, 0);
92  SuggestionsProfile filtered_suggestions;
93
94  // Store and load. Expired suggestions should not be loaded.
95  EXPECT_TRUE(suggestions_store_->StoreSuggestions(suggestions));
96  EXPECT_FALSE(suggestions_store_->LoadSuggestions(&filtered_suggestions));
97  EXPECT_EQ(0, filtered_suggestions.suggestions_size());
98}
99
100// Tests LoadSuggestions function to filter expired suggestions.
101TEST_F(SuggestionsStoreTest, LoadValidAndExpired) {
102  SuggestionsProfile suggestions = CreateTestSuggestionsProfileWithExpiry(5, 3);
103  SuggestionsProfile filtered_suggestions;
104
105  // Store and load. Expired suggestions should not be loaded.
106  EXPECT_TRUE(suggestions_store_->StoreSuggestions(suggestions));
107  EXPECT_TRUE(suggestions_store_->LoadSuggestions(&filtered_suggestions));
108  EXPECT_EQ(3, filtered_suggestions.suggestions_size());
109}
110
111// Tests LoadSuggestions function to filter expired suggestions.
112TEST_F(SuggestionsStoreTest, CheckStoreAfterLoadExpired) {
113  SuggestionsProfile suggestions = CreateTestSuggestionsProfileWithExpiry(5, 3);
114  SuggestionsProfile filtered_suggestions;
115
116  // Store and load. Expired suggestions should not be loaded.
117  EXPECT_TRUE(suggestions_store_->StoreSuggestions(suggestions));
118  EXPECT_TRUE(suggestions_store_->LoadSuggestions(&filtered_suggestions));
119
120  SuggestionsProfile loaded_suggestions;
121  EXPECT_TRUE(suggestions_store_->LoadSuggestions(&loaded_suggestions));
122  EXPECT_EQ(3, loaded_suggestions.suggestions_size());
123  ValidateSuggestions(filtered_suggestions, loaded_suggestions);
124}
125
126TEST_F(SuggestionsStoreTest, LoadStoreClear) {
127  const SuggestionsProfile suggestions = CreateTestSuggestions();
128  const SuggestionsProfile empty_suggestions;
129  SuggestionsProfile recovered_suggestions;
130
131  // Attempt to load when prefs are empty.
132  EXPECT_FALSE(suggestions_store_->LoadSuggestions(&recovered_suggestions));
133  ValidateSuggestions(empty_suggestions, recovered_suggestions);
134
135  // Store then reload.
136  EXPECT_TRUE(suggestions_store_->StoreSuggestions(suggestions));
137  EXPECT_TRUE(suggestions_store_->LoadSuggestions(&recovered_suggestions));
138  ValidateSuggestions(suggestions, recovered_suggestions);
139
140  // Clear.
141  suggestions_store_->ClearSuggestions();
142  EXPECT_FALSE(suggestions_store_->LoadSuggestions(&recovered_suggestions));
143  ValidateSuggestions(empty_suggestions, recovered_suggestions);
144}
145
146}  // namespace suggestions
147