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