OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 "ios/chrome/browser/reading_list/reading_list_entry.h" | |
6 | |
7 #include "base/memory/ptr_util.h" | |
8 #include "base/test/simple_test_tick_clock.h" | |
9 #include "components/sync/protocol/reading_list_specifics.pb.h" | |
10 #include "ios/chrome/browser/reading_list/proto/reading_list.pb.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 | |
13 namespace { | |
14 const int kFirstBackoff = 10; | |
15 const int kSecondBackoff = 10; | |
16 const int kThirdBackoff = 60; | |
17 const int kFourthBackoff = 120; | |
18 const int kFifthBackoff = 120; | |
19 } // namespace | |
20 | |
21 TEST(ReadingListEntry, CompareIgnoreTitle) { | |
22 const ReadingListEntry e1(GURL("http://example.com"), "bar"); | |
23 const ReadingListEntry e2(GURL("http://example.com"), "foo"); | |
24 | |
25 EXPECT_EQ(e1, e2); | |
26 } | |
27 | |
28 TEST(ReadingListEntry, CompareFailureIgnoreTitle) { | |
29 const ReadingListEntry e1(GURL("http://example.com"), "bar"); | |
30 const ReadingListEntry e2(GURL("http://example.org"), "bar"); | |
31 | |
32 EXPECT_FALSE(e1 == e2); | |
33 } | |
34 | |
35 TEST(ReadingListEntry, MovesAreEquals) { | |
36 ReadingListEntry e1(GURL("http://example.com"), "bar"); | |
37 ReadingListEntry e2(GURL("http://example.com"), "bar"); | |
38 ASSERT_EQ(e1, e2); | |
39 ASSERT_EQ(e1.Title(), e2.Title()); | |
40 | |
41 ReadingListEntry e3(std::move(e1)); | |
42 | |
43 EXPECT_EQ(e3, e2); | |
44 EXPECT_EQ(e3.Title(), e2.Title()); | |
45 } | |
46 | |
47 TEST(ReadingListEntry, DistilledPathAndURL) { | |
48 ReadingListEntry e(GURL("http://example.com"), "bar"); | |
49 | |
50 EXPECT_TRUE(e.DistilledPath().empty()); | |
51 | |
52 const base::FilePath distilled_path("distilled/page.html"); | |
53 e.SetDistilledPath(distilled_path); | |
54 EXPECT_EQ(distilled_path, e.DistilledPath()); | |
55 EXPECT_EQ(GURL("chrome://offline/distilled/page.html"), e.DistilledURL()); | |
56 } | |
57 | |
58 TEST(ReadingListEntry, DistilledState) { | |
59 ReadingListEntry e(GURL("http://example.com"), "bar"); | |
60 | |
61 EXPECT_EQ(ReadingListEntry::WAITING, e.DistilledState()); | |
62 | |
63 e.SetDistilledState(ReadingListEntry::ERROR); | |
64 EXPECT_EQ(ReadingListEntry::ERROR, e.DistilledState()); | |
65 | |
66 const base::FilePath distilled_path("distilled/page.html"); | |
67 e.SetDistilledPath(distilled_path); | |
68 EXPECT_EQ(ReadingListEntry::PROCESSED, e.DistilledState()); | |
69 } | |
70 | |
71 // Tests that the the time until next try increase exponentially when the state | |
72 // changes from non-error to error. | |
73 TEST(ReadingListEntry, TimeUntilNextTry) { | |
74 base::SimpleTestTickClock clock; | |
75 std::unique_ptr<net::BackoffEntry> backoff = | |
76 base::MakeUnique<net::BackoffEntry>(&ReadingListEntry::kBackoffPolicy, | |
77 &clock); | |
78 | |
79 ReadingListEntry e(GURL("http://example.com"), "bar", std::move(backoff)); | |
80 | |
81 double fuzzing = ReadingListEntry::kBackoffPolicy.jitter_factor; | |
82 | |
83 ASSERT_EQ(0, e.TimeUntilNextTry().InSeconds()); | |
84 | |
85 // First error. | |
86 e.SetDistilledState(ReadingListEntry::ERROR); | |
87 int nextTry = e.TimeUntilNextTry().InMinutes(); | |
88 EXPECT_NEAR(kFirstBackoff, nextTry, kFirstBackoff * fuzzing); | |
89 e.SetDistilledState(ReadingListEntry::WILL_RETRY); | |
90 EXPECT_EQ(nextTry, e.TimeUntilNextTry().InMinutes()); | |
91 | |
92 e.SetDistilledState(ReadingListEntry::PROCESSING); | |
93 EXPECT_EQ(nextTry, e.TimeUntilNextTry().InMinutes()); | |
94 | |
95 // Second error. | |
96 e.SetDistilledState(ReadingListEntry::WILL_RETRY); | |
97 nextTry = e.TimeUntilNextTry().InMinutes(); | |
98 EXPECT_NEAR(kSecondBackoff, nextTry, kSecondBackoff * fuzzing); | |
99 e.SetDistilledState(ReadingListEntry::ERROR); | |
100 EXPECT_EQ(nextTry, e.TimeUntilNextTry().InMinutes()); | |
101 | |
102 e.SetDistilledState(ReadingListEntry::PROCESSING); | |
103 EXPECT_EQ(nextTry, e.TimeUntilNextTry().InMinutes()); | |
104 | |
105 // Third error. | |
106 e.SetDistilledState(ReadingListEntry::WILL_RETRY); | |
107 EXPECT_NEAR(kThirdBackoff, e.TimeUntilNextTry().InMinutes(), | |
108 kThirdBackoff * fuzzing); | |
109 | |
110 // Fourth error. | |
111 e.SetDistilledState(ReadingListEntry::PROCESSING); | |
112 e.SetDistilledState(ReadingListEntry::ERROR); | |
113 EXPECT_NEAR(kFourthBackoff, e.TimeUntilNextTry().InMinutes(), | |
114 kFourthBackoff * fuzzing); | |
115 | |
116 // Fifth error. | |
117 e.SetDistilledState(ReadingListEntry::PROCESSING); | |
118 e.SetDistilledState(ReadingListEntry::ERROR); | |
119 EXPECT_NEAR(kFifthBackoff, e.TimeUntilNextTry().InMinutes(), | |
120 kFifthBackoff * fuzzing); | |
121 } | |
122 | |
123 // Tests that if the time until next try is in the past, 0 is returned. | |
124 TEST(ReadingListEntry, TimeUntilNextTryInThePast) { | |
125 // Setup. | |
126 base::SimpleTestTickClock clock; | |
127 std::unique_ptr<net::BackoffEntry> backoff = | |
128 base::MakeUnique<net::BackoffEntry>(&ReadingListEntry::kBackoffPolicy, | |
129 &clock); | |
130 ReadingListEntry e(GURL("http://example.com"), "bar", std::move(backoff)); | |
131 double fuzzing = ReadingListEntry::kBackoffPolicy.jitter_factor; | |
132 | |
133 e.SetDistilledState(ReadingListEntry::ERROR); | |
134 ASSERT_NEAR(kFirstBackoff, e.TimeUntilNextTry().InMinutes(), | |
135 kFirstBackoff * fuzzing); | |
136 | |
137 // Action. | |
138 clock.Advance(base::TimeDelta::FromMinutes(kFirstBackoff * 2)); | |
139 | |
140 // Test. | |
141 EXPECT_EQ(0, e.TimeUntilNextTry().InMilliseconds()); | |
142 } | |
143 | |
144 // Tests that if the entry gets a distilled URL, 0 is returned. | |
145 TEST(ReadingListEntry, ResetTimeUntilNextTry) { | |
146 // Setup. | |
147 base::SimpleTestTickClock clock; | |
148 std::unique_ptr<net::BackoffEntry> backoff = | |
149 base::MakeUnique<net::BackoffEntry>(&ReadingListEntry::kBackoffPolicy, | |
150 &clock); | |
151 ReadingListEntry e(GURL("http://example.com"), "bar", std::move(backoff)); | |
152 double fuzzing = ReadingListEntry::kBackoffPolicy.jitter_factor; | |
153 | |
154 e.SetDistilledState(ReadingListEntry::ERROR); | |
155 ASSERT_NEAR(kFirstBackoff, e.TimeUntilNextTry().InMinutes(), | |
156 kFirstBackoff * fuzzing); | |
157 | |
158 // Action. | |
159 e.SetDistilledPath(base::FilePath("distilled/page.html")); | |
160 | |
161 // Test. | |
162 EXPECT_EQ(0, e.TimeUntilNextTry().InSeconds()); | |
163 e.SetDistilledState(ReadingListEntry::ERROR); | |
164 ASSERT_NEAR(kFirstBackoff, e.TimeUntilNextTry().InMinutes(), | |
165 kFirstBackoff * fuzzing); | |
166 } | |
167 | |
168 // Tests that the failed download counter is incremented when the state change | |
169 // from non-error to error. | |
170 TEST(ReadingListEntry, FailedDownloadCounter) { | |
171 ReadingListEntry e(GURL("http://example.com"), "bar"); | |
172 | |
173 ASSERT_EQ(0, e.FailedDownloadCounter()); | |
174 | |
175 e.SetDistilledState(ReadingListEntry::ERROR); | |
176 EXPECT_EQ(1, e.FailedDownloadCounter()); | |
177 e.SetDistilledState(ReadingListEntry::WILL_RETRY); | |
178 EXPECT_EQ(1, e.FailedDownloadCounter()); | |
179 | |
180 e.SetDistilledState(ReadingListEntry::PROCESSING); | |
181 EXPECT_EQ(1, e.FailedDownloadCounter()); | |
182 | |
183 e.SetDistilledState(ReadingListEntry::WILL_RETRY); | |
184 EXPECT_EQ(2, e.FailedDownloadCounter()); | |
185 e.SetDistilledState(ReadingListEntry::ERROR); | |
186 EXPECT_EQ(2, e.FailedDownloadCounter()); | |
187 } | |
188 | |
189 // Tests that the reading list entry is correctly encoded to | |
190 // sync_pb::ReadingListSpecifics. | |
191 TEST(ReadingListEntry, AsReadingListSpecifics) { | |
192 ReadingListEntry entry(GURL("http://example.com/"), "bar"); | |
193 int64_t creation_time_us = entry.UpdateTime(); | |
194 | |
195 std::unique_ptr<sync_pb::ReadingListSpecifics> pb_entry( | |
196 entry.AsReadingListSpecifics(false)); | |
197 EXPECT_EQ(pb_entry->entry_id(), "http://example.com/"); | |
198 EXPECT_EQ(pb_entry->url(), "http://example.com/"); | |
199 EXPECT_EQ(pb_entry->title(), "bar"); | |
200 EXPECT_EQ(pb_entry->creation_time_us(), creation_time_us); | |
201 EXPECT_EQ(pb_entry->update_time_us(), entry.UpdateTime()); | |
202 EXPECT_EQ(pb_entry->status(), sync_pb::ReadingListSpecifics::UNREAD); | |
203 | |
204 entry.MarkEntryUpdated(); | |
205 EXPECT_NE(entry.UpdateTime(), creation_time_us); | |
206 std::unique_ptr<sync_pb::ReadingListSpecifics> updated_pb_entry( | |
207 entry.AsReadingListSpecifics(true)); | |
208 EXPECT_EQ(updated_pb_entry->creation_time_us(), creation_time_us); | |
209 EXPECT_EQ(updated_pb_entry->update_time_us(), entry.UpdateTime()); | |
210 EXPECT_EQ(updated_pb_entry->status(), sync_pb::ReadingListSpecifics::READ); | |
211 } | |
212 | |
213 // Tests that the reading list entry is correctly parsed from | |
214 // sync_pb::ReadingListSpecifics. | |
215 TEST(ReadingListEntry, FromReadingListSpecifics) { | |
216 std::unique_ptr<sync_pb::ReadingListSpecifics> pb_entry = | |
217 base::MakeUnique<sync_pb::ReadingListSpecifics>(); | |
218 pb_entry->set_entry_id("http://example.com/"); | |
219 pb_entry->set_url("http://example.com/"); | |
220 pb_entry->set_title("title"); | |
221 pb_entry->set_creation_time_us(1); | |
222 pb_entry->set_update_time_us(2); | |
223 pb_entry->set_status(sync_pb::ReadingListSpecifics::UNREAD); | |
224 | |
225 std::unique_ptr<ReadingListEntry> entry( | |
226 ReadingListEntry::FromReadingListSpecifics(*pb_entry)); | |
227 EXPECT_EQ(entry->URL().spec(), "http://example.com/"); | |
228 EXPECT_EQ(entry->Title(), "title"); | |
229 EXPECT_EQ(entry->UpdateTime(), 2); | |
230 EXPECT_EQ(entry->FailedDownloadCounter(), 0); | |
231 } | |
232 | |
233 // Tests that the reading list entry is correctly encoded to | |
234 // reading_list::ReadingListLocal. | |
235 TEST(ReadingListEntry, AsReadingListLocal) { | |
236 ReadingListEntry entry(GURL("http://example.com/"), "bar"); | |
237 int64_t creation_time_us = entry.UpdateTime(); | |
238 | |
239 std::unique_ptr<reading_list::ReadingListLocal> pb_entry( | |
240 entry.AsReadingListLocal(false)); | |
241 EXPECT_EQ(pb_entry->entry_id(), "http://example.com/"); | |
242 EXPECT_EQ(pb_entry->url(), "http://example.com/"); | |
243 EXPECT_EQ(pb_entry->title(), "bar"); | |
244 EXPECT_EQ(pb_entry->creation_time_us(), creation_time_us); | |
245 EXPECT_EQ(pb_entry->update_time_us(), entry.UpdateTime()); | |
246 EXPECT_EQ(pb_entry->status(), reading_list::ReadingListLocal::UNREAD); | |
247 EXPECT_EQ(pb_entry->distillation_state(), | |
248 reading_list::ReadingListLocal::WAITING); | |
249 EXPECT_EQ(pb_entry->distilled_path(), ""); | |
250 EXPECT_EQ(pb_entry->failed_download_counter(), 0); | |
251 EXPECT_NE(pb_entry->backoff(), ""); | |
252 | |
253 entry.SetDistilledState(ReadingListEntry::WILL_RETRY); | |
254 std::unique_ptr<reading_list::ReadingListLocal> will_retry_pb_entry( | |
255 entry.AsReadingListLocal(true)); | |
256 EXPECT_EQ(will_retry_pb_entry->distillation_state(), | |
257 reading_list::ReadingListLocal::WILL_RETRY); | |
258 EXPECT_EQ(will_retry_pb_entry->failed_download_counter(), 1); | |
259 | |
260 entry.SetDistilledPath(base::FilePath("distilled/page.html")); | |
261 entry.MarkEntryUpdated(); | |
262 EXPECT_NE(entry.UpdateTime(), creation_time_us); | |
263 std::unique_ptr<reading_list::ReadingListLocal> distilled_pb_entry( | |
264 entry.AsReadingListLocal(true)); | |
265 EXPECT_EQ(distilled_pb_entry->creation_time_us(), creation_time_us); | |
266 EXPECT_EQ(distilled_pb_entry->update_time_us(), entry.UpdateTime()); | |
267 EXPECT_NE(distilled_pb_entry->backoff(), ""); | |
268 EXPECT_EQ(distilled_pb_entry->status(), reading_list::ReadingListLocal::READ); | |
269 EXPECT_EQ(distilled_pb_entry->distillation_state(), | |
270 reading_list::ReadingListLocal::PROCESSED); | |
271 EXPECT_EQ(distilled_pb_entry->distilled_path(), "distilled/page.html"); | |
272 EXPECT_EQ(distilled_pb_entry->failed_download_counter(), 0); | |
273 } | |
274 | |
275 // Tests that the reading list entry is correctly parsed from | |
276 // sync_pb::ReadingListLocal. | |
277 TEST(ReadingListEntry, FromReadingListLocal) { | |
278 ReadingListEntry entry(GURL("http://example.com/"), "title"); | |
279 base::Time next_call = base::Time::Now() + entry.TimeUntilNextTry(); | |
280 | |
281 std::unique_ptr<reading_list::ReadingListLocal> pb_entry( | |
282 entry.AsReadingListLocal(false)); | |
283 | |
284 pb_entry->set_entry_id("http://example.com/"); | |
285 pb_entry->set_url("http://example.com/"); | |
286 pb_entry->set_title("title"); | |
287 pb_entry->set_creation_time_us(1); | |
288 pb_entry->set_update_time_us(2); | |
289 pb_entry->set_status(reading_list::ReadingListLocal::UNREAD); | |
290 pb_entry->set_distillation_state(reading_list::ReadingListLocal::WAITING); | |
291 pb_entry->set_failed_download_counter(2); | |
292 | |
293 std::unique_ptr<ReadingListEntry> waiting_entry( | |
294 ReadingListEntry::FromReadingListLocal(*pb_entry)); | |
295 EXPECT_EQ(waiting_entry->URL().spec(), "http://example.com/"); | |
296 EXPECT_EQ(waiting_entry->Title(), "title"); | |
297 EXPECT_EQ(waiting_entry->UpdateTime(), 2); | |
298 EXPECT_EQ(waiting_entry->FailedDownloadCounter(), 2); | |
299 EXPECT_EQ(waiting_entry->DistilledState(), ReadingListEntry::WAITING); | |
300 EXPECT_EQ(waiting_entry->DistilledPath(), base::FilePath()); | |
301 base::Time waiting_next_call = | |
302 base::Time::Now() + waiting_entry->TimeUntilNextTry(); | |
303 base::TimeDelta delta = next_call - waiting_next_call; | |
304 EXPECT_NEAR(delta.InMillisecondsRoundedUp(), 0, 10); | |
305 } | |
306 | |
307 // Tests that the merging of two ReadingListEntry. | |
308 TEST(ReadingListEntry, MergeLocalStateFrom) { | |
309 ReadingListEntry local_entry(GURL("http://example.com/"), "title"); | |
310 base::Time next_call = base::Time::Now() + local_entry.TimeUntilNextTry(); | |
311 int64_t local_update_time_us = local_entry.UpdateTime(); | |
312 local_entry.SetDistilledPath(base::FilePath("distilled/page.html")); | |
313 | |
314 ReadingListEntry sync_entry(GURL("http://example2.com/"), "title2"); | |
315 sync_entry.SetDistilledState(ReadingListEntry::ERROR); | |
316 int64_t sync_update_time_us = sync_entry.UpdateTime(); | |
317 EXPECT_NE(local_update_time_us, sync_update_time_us); | |
318 sync_entry.MergeLocalStateFrom(local_entry); | |
319 EXPECT_EQ(sync_entry.URL().spec(), "http://example2.com/"); | |
320 EXPECT_EQ(sync_entry.Title(), "title2"); | |
321 EXPECT_EQ(sync_entry.UpdateTime(), sync_update_time_us); | |
322 EXPECT_EQ(sync_entry.FailedDownloadCounter(), 0); | |
323 EXPECT_EQ(sync_entry.DistilledState(), ReadingListEntry::PROCESSED); | |
324 EXPECT_EQ(sync_entry.DistilledPath().value(), "distilled/page.html"); | |
325 base::Time sync_next_call = base::Time::Now() + sync_entry.TimeUntilNextTry(); | |
326 base::TimeDelta delta = next_call - sync_next_call; | |
327 EXPECT_NEAR(delta.InMillisecondsRoundedUp(), 0, 10); | |
328 } | |
OLD | NEW |