| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/ntp_snippets/ntp_snippets_service.h" | 5 #include "components/ntp_snippets/ntp_snippets_service.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <vector> |
| 8 | 9 |
| 9 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
| 10 #include "base/macros.h" | 11 #include "base/macros.h" |
| 11 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 12 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 15 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 16 #include "base/test/histogram_tester.h" | 17 #include "base/test/histogram_tester.h" |
| 17 #include "base/thread_task_runner_handle.h" | 18 #include "base/thread_task_runner_handle.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 35 base::Time GetDefaultCreationTime() { | 36 base::Time GetDefaultCreationTime() { |
| 36 return base::Time::FromUTCExploded(kDefaultCreationTime); | 37 return base::Time::FromUTCExploded(kDefaultCreationTime); |
| 37 } | 38 } |
| 38 | 39 |
| 39 std::string GetTestJson(const std::string& content_creation_time_str, | 40 std::string GetTestJson(const std::string& content_creation_time_str, |
| 40 const std::string& expiry_time_str) { | 41 const std::string& expiry_time_str) { |
| 41 char json_str_format[] = | 42 char json_str_format[] = |
| 42 "{ \"recos\": [ " | 43 "{ \"recos\": [ " |
| 43 "{ \"contentInfo\": {" | 44 "{ \"contentInfo\": {" |
| 44 "\"url\" : \"http://localhost/foobar\"," | 45 "\"url\" : \"http://localhost/foobar\"," |
| 45 "\"site_title\" : \"Site Title\"," | |
| 46 "\"favicon_url\" : \"http://localhost/favicon\"," | |
| 47 "\"title\" : \"Title\"," | 46 "\"title\" : \"Title\"," |
| 48 "\"snippet\" : \"Snippet\"," | 47 "\"snippet\" : \"Snippet\"," |
| 49 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," | 48 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," |
| 50 "\"creationTimestampSec\" : \"%s\"," | 49 "\"creationTimestampSec\" : \"%s\"," |
| 51 "\"expiryTimestampSec\" : \"%s\"," | 50 "\"expiryTimestampSec\" : \"%s\"," |
| 52 "\"sourceCorpusInfo\" : [ " | 51 "\"sourceCorpusInfo\" : [ " |
| 53 "{\"ampUrl\" : \"http://localhost/amp\"}," | 52 "{\"ampUrl\" : \"http://localhost/amp\"," |
| 54 "{\"corpusId\" : \"id\"}]" | 53 "\"corpusId\" : \"http://localhost/foobar\"," |
| 54 "\"publisherData\": { \"sourceName\" : \"Foo News\"}}]" |
| 55 "}}" | 55 "}}" |
| 56 "]}"; | 56 "]}"; |
| 57 | 57 |
| 58 return base::StringPrintf(json_str_format, content_creation_time_str.c_str(), | 58 return base::StringPrintf(json_str_format, content_creation_time_str.c_str(), |
| 59 expiry_time_str.c_str()); | 59 expiry_time_str.c_str()); |
| 60 } | 60 } |
| 61 | 61 |
| 62 std::string GetTestJsonWithSources(const std::string& content_creation_time_str, |
| 63 const std::string& expiry_time_str, |
| 64 const std::vector<std::string>& source_urls, |
| 65 const std::vector<std::string>& publishers, |
| 66 const std::vector<std::string>& amp_urls) { |
| 67 char json_str_format[] = |
| 68 "{ \"recos\": [ " |
| 69 "{ \"contentInfo\": {" |
| 70 "\"url\" : \"http://localhost/foobar\"," |
| 71 "\"title\" : \"Title\"," |
| 72 "\"snippet\" : \"Snippet\"," |
| 73 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," |
| 74 "\"creationTimestampSec\" : \"%s\"," |
| 75 "\"expiryTimestampSec\" : \"%s\"," |
| 76 "\"sourceCorpusInfo\" : [%s]" |
| 77 "}}" |
| 78 "]}"; |
| 79 |
| 80 char source_corpus_info_format[] = |
| 81 "{\"corpusId\": \"%s\"," |
| 82 "\"publisherData\": {" |
| 83 "\"sourceName\": \"%s\"" |
| 84 "}," |
| 85 "\"ampUrl\": \"%s\"}"; |
| 86 |
| 87 std::string source_corpus_info_list_str; |
| 88 for (size_t i = 0; i < source_urls.size(); ++i) { |
| 89 std::string source_corpus_info_str = |
| 90 base::StringPrintf(source_corpus_info_format, |
| 91 source_urls[i].empty() ? "" : source_urls[i].c_str(), |
| 92 publishers[i].empty() ? "" : publishers[i].c_str(), |
| 93 amp_urls[i].empty() ? "" : amp_urls[i].c_str()); |
| 94 source_corpus_info_list_str.append(source_corpus_info_str); |
| 95 source_corpus_info_list_str.append(","); |
| 96 } |
| 97 // Remove the last comma |
| 98 source_corpus_info_list_str.pop_back(); |
| 99 return base::StringPrintf(json_str_format, content_creation_time_str.c_str(), |
| 100 expiry_time_str.c_str(), |
| 101 source_corpus_info_list_str.c_str()); |
| 102 } |
| 103 |
| 104 std::string GetTestJsonWithSources(const std::vector<std::string>& source_urls, |
| 105 const std::vector<std::string>& publishers, |
| 106 const std::vector<std::string>& amp_urls) { |
| 107 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); |
| 108 return GetTestJsonWithSources( |
| 109 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()), |
| 110 NTPSnippet::TimeToJsonString(expiry_time), source_urls, publishers, |
| 111 amp_urls); |
| 112 } |
| 113 |
| 62 std::string GetTestJson(const std::string& content_creation_time_str) { | 114 std::string GetTestJson(const std::string& content_creation_time_str) { |
| 63 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); | 115 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); |
| 64 return GetTestJson(content_creation_time_str, | 116 return GetTestJson(content_creation_time_str, |
| 65 NTPSnippet::TimeToJsonString(expiry_time)); | 117 NTPSnippet::TimeToJsonString(expiry_time)); |
| 66 } | 118 } |
| 67 | 119 |
| 68 std::string GetTestJson() { | 120 std::string GetTestJson() { |
| 69 return GetTestJson(NTPSnippet::TimeToJsonString(GetDefaultCreationTime())); | 121 return GetTestJson(NTPSnippet::TimeToJsonString(GetDefaultCreationTime())); |
| 70 } | 122 } |
| 71 | 123 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 TEST_F(NTPSnippetsServiceTest, Full) { | 265 TEST_F(NTPSnippetsServiceTest, Full) { |
| 214 std::string json_str(GetTestJson()); | 266 std::string json_str(GetTestJson()); |
| 215 | 267 |
| 216 LoadFromJSONString(json_str); | 268 LoadFromJSONString(json_str); |
| 217 EXPECT_EQ(service()->size(), 1u); | 269 EXPECT_EQ(service()->size(), 1u); |
| 218 | 270 |
| 219 // The same for loop without the '&' should not compile. | 271 // The same for loop without the '&' should not compile. |
| 220 for (auto& snippet : *service()) { | 272 for (auto& snippet : *service()) { |
| 221 // Snippet here is a const. | 273 // Snippet here is a const. |
| 222 EXPECT_EQ(snippet.url(), GURL("http://localhost/foobar")); | 274 EXPECT_EQ(snippet.url(), GURL("http://localhost/foobar")); |
| 223 EXPECT_EQ(snippet.site_title(), "Site Title"); | 275 EXPECT_EQ(snippet.best_source().publisher_name, "Foo News"); |
| 224 EXPECT_EQ(snippet.favicon_url(), GURL("http://localhost/favicon")); | |
| 225 EXPECT_EQ(snippet.title(), "Title"); | 276 EXPECT_EQ(snippet.title(), "Title"); |
| 226 EXPECT_EQ(snippet.snippet(), "Snippet"); | 277 EXPECT_EQ(snippet.snippet(), "Snippet"); |
| 227 EXPECT_EQ(snippet.salient_image_url(), | 278 EXPECT_EQ(snippet.salient_image_url(), |
| 228 GURL("http://localhost/salient_image")); | 279 GURL("http://localhost/salient_image")); |
| 229 EXPECT_EQ(GetDefaultCreationTime(), snippet.publish_date()); | 280 EXPECT_EQ(GetDefaultCreationTime(), snippet.publish_date()); |
| 230 EXPECT_EQ(snippet.amp_url(), GURL("http://localhost/amp")); | 281 EXPECT_EQ(snippet.best_source().amp_url.spec(), |
| 282 GURL("http://localhost/amp").spec()); |
| 231 } | 283 } |
| 232 } | 284 } |
| 233 | 285 |
| 234 TEST_F(NTPSnippetsServiceTest, Clear) { | 286 TEST_F(NTPSnippetsServiceTest, Clear) { |
| 235 std::string json_str(GetTestJson()); | 287 std::string json_str(GetTestJson()); |
| 236 | 288 |
| 237 LoadFromJSONString(json_str); | 289 LoadFromJSONString(json_str); |
| 238 EXPECT_EQ(service()->size(), 1u); | 290 EXPECT_EQ(service()->size(), 1u); |
| 239 | 291 |
| 240 service()->ClearSnippets(); | 292 service()->ClearSnippets(); |
| 241 EXPECT_EQ(service()->size(), 0u); | 293 EXPECT_EQ(service()->size(), 0u); |
| 242 } | 294 } |
| 243 | 295 |
| 244 TEST_F(NTPSnippetsServiceTest, InsertAtFront) { | 296 TEST_F(NTPSnippetsServiceTest, InsertAtFront) { |
| 245 std::string json_str( | 297 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); |
| 298 char json_str_format[] = |
| 246 "{ \"recos\": [ " | 299 "{ \"recos\": [ " |
| 247 " { \"contentInfo\": { \"url\" : \"http://first\" }}" | 300 "{ \"contentInfo\": {" |
| 248 "]}"); | 301 "\"url\" : \"%s\"," |
| 302 "\"title\" : \"Title\"," |
| 303 "\"snippet\" : \"Snippet\"," |
| 304 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," |
| 305 "\"creationTimestampSec\" : \"%s\"," |
| 306 "\"expiryTimestampSec\" : \"%s\"," |
| 307 "\"sourceCorpusInfo\" : [{\"corpusId\": \"http://first\"," |
| 308 "\"publisherData\": {" |
| 309 "\"sourceName\": \"Source 1\"" |
| 310 "}," |
| 311 "\"ampUrl\": \"\"}]" |
| 312 "}}" |
| 313 "]}"; |
| 314 std::string json_str(base::StringPrintf( |
| 315 json_str_format, "http://first", |
| 316 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 317 NTPSnippet::TimeToJsonString(expiry_time).c_str())); |
| 318 |
| 249 LoadFromJSONString(json_str); | 319 LoadFromJSONString(json_str); |
| 320 |
| 250 ASSERT_EQ(service()->size(), 1u); | 321 ASSERT_EQ(service()->size(), 1u); |
| 251 | 322 |
| 252 std::string json_str2( | 323 json_str = base::StringPrintf( |
| 253 "{ \"recos\": [ " | 324 json_str_format, "http://second", |
| 254 " { \"contentInfo\": { \"url\" : \"http://second\" }}" | 325 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 255 "]}"); | 326 NTPSnippet::TimeToJsonString(expiry_time).c_str()); |
| 256 LoadFromJSONString(json_str2); | 327 |
| 328 LoadFromJSONString(json_str); |
| 257 ASSERT_EQ(service()->size(), 2u); | 329 ASSERT_EQ(service()->size(), 2u); |
| 258 | 330 |
| 259 // The snippet loaded last should be at the first position in the list now. | 331 // The snippet loaded last should be at the first position in the list now. |
| 260 const NTPSnippet& first_snippet = *service()->begin(); | 332 const NTPSnippet& first_snippet = *service()->begin(); |
| 261 EXPECT_EQ(first_snippet.url(), GURL("http://second")); | 333 EXPECT_EQ(first_snippet.url(), GURL("http://second")); |
| 262 } | 334 } |
| 263 | 335 |
| 264 TEST_F(NTPSnippetsServiceTest, LimitNumSnippets) { | 336 TEST_F(NTPSnippetsServiceTest, LimitNumSnippets) { |
| 265 int max_snippet_count = NTPSnippetsService::GetMaxSnippetCountForTesting(); | 337 int max_snippet_count = NTPSnippetsService::GetMaxSnippetCountForTesting(); |
| 266 int snippets_per_load = max_snippet_count / 2 + 1; | 338 int snippets_per_load = max_snippet_count / 2 + 1; |
| 267 | 339 |
| 268 const char snippet_format[] = | 340 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); |
| 269 "{ \"contentInfo\": { \"url\" : \"http://localhost/%i\" }}"; | 341 char json_str_format[] = |
| 342 "{ \"contentInfo\": {" |
| 343 "\"url\" : \"http://localhost/%i\"," |
| 344 "\"title\" : \"Title\"," |
| 345 "\"snippet\" : \"Snippet\"," |
| 346 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," |
| 347 "\"creationTimestampSec\" : \"%s\"," |
| 348 "\"expiryTimestampSec\" : \"%s\"," |
| 349 "\"sourceCorpusInfo\" : [{\"corpusId\": \"http://first\"," |
| 350 "\"publisherData\": {" |
| 351 "\"sourceName\": \"Source 1\"" |
| 352 "}," |
| 353 "\"ampUrl\": \"\"}]" |
| 354 "}}"; |
| 355 |
| 270 std::vector<std::string> snippets1; | 356 std::vector<std::string> snippets1; |
| 271 std::vector<std::string> snippets2; | 357 std::vector<std::string> snippets2; |
| 272 for (int i = 0; i < snippets_per_load; i++) { | 358 for (int i = 0; i < snippets_per_load; i++) { |
| 273 snippets1.push_back(base::StringPrintf(snippet_format, i)); | 359 snippets1.push_back(base::StringPrintf( |
| 274 snippets2.push_back(base::StringPrintf(snippet_format, | 360 json_str_format, i, |
| 275 snippets_per_load + i)); | 361 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 362 NTPSnippet::TimeToJsonString(expiry_time).c_str())); |
| 363 snippets2.push_back(base::StringPrintf( |
| 364 json_str_format, snippets_per_load + i, |
| 365 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), |
| 366 NTPSnippet::TimeToJsonString(expiry_time).c_str())); |
| 276 } | 367 } |
| 277 | 368 |
| 278 LoadFromJSONString( | 369 LoadFromJSONString( |
| 279 "{ \"recos\": [ " + base::JoinString(snippets1, ", ") + "]}"); | 370 "{ \"recos\": [ " + base::JoinString(snippets1, ", ") + "]}"); |
| 280 ASSERT_EQ(snippets1.size(), service()->size()); | 371 ASSERT_EQ(snippets1.size(), service()->size()); |
| 281 | 372 |
| 282 LoadFromJSONString( | 373 LoadFromJSONString( |
| 283 "{ \"recos\": [ " + base::JoinString(snippets2, ", ") + "]}"); | 374 "{ \"recos\": [ " + base::JoinString(snippets2, ", ") + "]}"); |
| 284 EXPECT_EQ(max_snippet_count, (int)service()->size()); | 375 EXPECT_EQ(max_snippet_count, (int)service()->size()); |
| 285 } | 376 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 308 TEST_F(NTPSnippetsServiceTest, LoadIncompleteJsonWithExistingSnippets) { | 399 TEST_F(NTPSnippetsServiceTest, LoadIncompleteJsonWithExistingSnippets) { |
| 309 LoadFromJSONString(GetTestJson()); | 400 LoadFromJSONString(GetTestJson()); |
| 310 ASSERT_EQ(service()->size(), 1u); | 401 ASSERT_EQ(service()->size(), 1u); |
| 311 | 402 |
| 312 LoadFromJSONString(GetIncompleteJson()); | 403 LoadFromJSONString(GetIncompleteJson()); |
| 313 // This should not have changed the existing snippets. | 404 // This should not have changed the existing snippets. |
| 314 EXPECT_EQ(service()->size(), 1u); | 405 EXPECT_EQ(service()->size(), 1u); |
| 315 } | 406 } |
| 316 | 407 |
| 317 TEST_F(NTPSnippetsServiceTest, Discard) { | 408 TEST_F(NTPSnippetsServiceTest, Discard) { |
| 409 std::vector<std::string> source_urls, publishers, amp_urls; |
| 410 source_urls.push_back(std::string("http://site.com")); |
| 411 publishers.push_back(std::string("Source 1")); |
| 412 amp_urls.push_back(std::string()); |
| 318 std::string json_str( | 413 std::string json_str( |
| 319 "{ \"recos\": [ { \"contentInfo\": { \"url\" : \"http://site.com\" }}]}"); | 414 GetTestJsonWithSources(source_urls, publishers, amp_urls)); |
| 415 |
| 320 LoadFromJSONString(json_str); | 416 LoadFromJSONString(json_str); |
| 321 | 417 |
| 322 ASSERT_EQ(1u, service()->size()); | 418 ASSERT_EQ(1u, service()->size()); |
| 323 | 419 |
| 324 // Discarding a non-existent snippet shouldn't do anything. | 420 // Discarding a non-existent snippet shouldn't do anything. |
| 325 EXPECT_FALSE(service()->DiscardSnippet(GURL("http://othersite.com"))); | 421 EXPECT_FALSE(service()->DiscardSnippet(GURL("http://othersite.com"))); |
| 326 EXPECT_EQ(1u, service()->size()); | 422 EXPECT_EQ(1u, service()->size()); |
| 327 | 423 |
| 328 // Discard the snippet. | 424 // Discard the snippet. |
| 329 EXPECT_TRUE(service()->DiscardSnippet(GURL("http://site.com"))); | 425 EXPECT_TRUE(service()->DiscardSnippet(GURL("http://localhost/foobar"))); |
| 330 EXPECT_EQ(0u, service()->size()); | 426 EXPECT_EQ(0u, service()->size()); |
| 331 | 427 |
| 332 // Make sure that fetching the same snippet again does not re-add it. | 428 // Make sure that fetching the same snippet again does not re-add it. |
| 333 LoadFromJSONString(json_str); | 429 LoadFromJSONString(json_str); |
| 334 EXPECT_EQ(0u, service()->size()); | 430 EXPECT_EQ(0u, service()->size()); |
| 335 | 431 |
| 336 // The snippet should stay discarded even after re-creating the service. | 432 // The snippet should stay discarded even after re-creating the service. |
| 337 CreateSnippetsService(); | 433 CreateSnippetsService(); |
| 338 LoadFromJSONString(json_str); | 434 LoadFromJSONString(json_str); |
| 339 EXPECT_EQ(0u, service()->size()); | 435 EXPECT_EQ(0u, service()->size()); |
| 340 | 436 |
| 341 // The snippet can be added again after clearing discarded snippets. | 437 // The snippet can be added again after clearing discarded snippets. |
| 342 service()->ClearDiscardedSnippets(); | 438 service()->ClearDiscardedSnippets(); |
| 343 EXPECT_EQ(0u, service()->size()); | 439 EXPECT_EQ(0u, service()->size()); |
| 344 LoadFromJSONString(json_str); | 440 LoadFromJSONString(json_str); |
| 345 EXPECT_EQ(1u, service()->size()); | 441 EXPECT_EQ(1u, service()->size()); |
| 346 } | 442 } |
| 347 | 443 |
| 348 TEST_F(NTPSnippetsServiceTest, GetDiscarded) { | 444 TEST_F(NTPSnippetsServiceTest, GetDiscarded) { |
| 349 std::string json_str( | 445 LoadFromJSONString(GetTestJson()); |
| 350 "{ \"recos\": [ { \"contentInfo\": { \"url\" : \"http://site.com\" }}]}"); | |
| 351 LoadFromJSONString(json_str); | |
| 352 | 446 |
| 353 // For the test, we need the snippet to get discarded. | 447 // For the test, we need the snippet to get discarded. |
| 354 ASSERT_TRUE(service()->DiscardSnippet(GURL("http://site.com"))); | 448 ASSERT_TRUE(service()->DiscardSnippet(GURL("http://localhost/foobar"))); |
| 355 const NTPSnippetsService::NTPSnippetStorage& snippets = | 449 const NTPSnippetsService::NTPSnippetStorage& snippets = |
| 356 service()->discarded_snippets(); | 450 service()->discarded_snippets(); |
| 357 EXPECT_EQ(1u, snippets.size()); | 451 EXPECT_EQ(1u, snippets.size()); |
| 358 for (auto& snippet : snippets) { | 452 for (auto& snippet : snippets) { |
| 359 EXPECT_EQ(GURL("http://site.com"), snippet->url()); | 453 EXPECT_EQ(GURL("http://localhost/foobar"), snippet->url()); |
| 360 } | 454 } |
| 361 | 455 |
| 362 // There should be no discarded snippet after clearing the list. | 456 // There should be no discarded snippet after clearing the list. |
| 363 service()->ClearDiscardedSnippets(); | 457 service()->ClearDiscardedSnippets(); |
| 364 EXPECT_EQ(0u, service()->discarded_snippets().size()); | 458 EXPECT_EQ(0u, service()->discarded_snippets().size()); |
| 365 } | 459 } |
| 366 | 460 |
| 367 TEST_F(NTPSnippetsServiceTest, CreationTimestampParseFail) { | 461 TEST_F(NTPSnippetsServiceTest, CreationTimestampParseFail) { |
| 368 std::string json_str(GetTestJson("aaa1448459205")); | 462 std::string json_str(GetTestJson("aaa1448459205")); |
| 369 | 463 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 380 } | 474 } |
| 381 } | 475 } |
| 382 | 476 |
| 383 TEST_F(NTPSnippetsServiceTest, RemoveExpiredContent) { | 477 TEST_F(NTPSnippetsServiceTest, RemoveExpiredContent) { |
| 384 std::string json_str(GetTestExpiredJson()); | 478 std::string json_str(GetTestExpiredJson()); |
| 385 | 479 |
| 386 LoadFromJSONString(json_str); | 480 LoadFromJSONString(json_str); |
| 387 EXPECT_EQ(service()->size(), 0u); | 481 EXPECT_EQ(service()->size(), 0u); |
| 388 } | 482 } |
| 389 | 483 |
| 484 TEST_F(NTPSnippetsServiceTest, TestSingleSource) { |
| 485 std::vector<std::string> source_urls, publishers, amp_urls; |
| 486 source_urls.push_back(std::string("http://source1.com")); |
| 487 publishers.push_back(std::string("Source 1")); |
| 488 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 489 std::string json_str( |
| 490 GetTestJsonWithSources(source_urls, publishers, amp_urls)); |
| 491 |
| 492 LoadFromJSONString(json_str); |
| 493 |
| 494 EXPECT_EQ(service()->size(), 1u); |
| 495 |
| 496 for (auto& snippet : *service()) { |
| 497 EXPECT_EQ(snippet.sources().size(), 1u); |
| 498 EXPECT_EQ(snippet.url(), GURL("http://localhost/foobar")); |
| 499 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); |
| 500 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); |
| 501 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source1.amp.com")); |
| 502 } |
| 503 } |
| 504 |
| 505 TEST_F(NTPSnippetsServiceTest, TestSingleSourceWithMalformedUrl) { |
| 506 std::vector<std::string> source_urls, publishers, amp_urls; |
| 507 source_urls.push_back(std::string("aaaa")); |
| 508 publishers.push_back(std::string("Source 1")); |
| 509 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 510 std::string json_str( |
| 511 GetTestJsonWithSources(source_urls, publishers, amp_urls)); |
| 512 |
| 513 LoadFromJSONString(json_str); |
| 514 EXPECT_EQ(service()->size(), 0u); |
| 515 } |
| 516 |
| 517 TEST_F(NTPSnippetsServiceTest, TestSingleSourceWithMissingData) { |
| 518 std::vector<std::string> source_urls, publishers, amp_urls; |
| 519 source_urls.push_back(std::string("http://source1.com")); |
| 520 publishers.push_back(std::string()); |
| 521 amp_urls.push_back(std::string()); |
| 522 std::string json_str( |
| 523 GetTestJsonWithSources(source_urls, publishers, amp_urls)); |
| 524 |
| 525 LoadFromJSONString(json_str); |
| 526 EXPECT_EQ(service()->size(), 0u); |
| 527 } |
| 528 |
| 529 TEST_F(NTPSnippetsServiceTest, TestMultipleSources) { |
| 530 std::vector<std::string> source_urls, publishers, amp_urls; |
| 531 source_urls.push_back(std::string("http://source1.com")); |
| 532 source_urls.push_back(std::string("http://source2.com")); |
| 533 publishers.push_back(std::string("Source 1")); |
| 534 publishers.push_back(std::string("Source 2")); |
| 535 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 536 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 537 std::string json_str( |
| 538 GetTestJsonWithSources(source_urls, publishers, amp_urls)); |
| 539 |
| 540 LoadFromJSONString(json_str); |
| 541 EXPECT_EQ(service()->size(), 1u); |
| 542 |
| 543 // Expect the first source to be chosen |
| 544 for (auto& snippet : *service()) { |
| 545 EXPECT_EQ(snippet.sources().size(), 2u); |
| 546 EXPECT_EQ(snippet.url(), GURL("http://localhost/foobar")); |
| 547 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); |
| 548 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); |
| 549 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source1.amp.com")); |
| 550 } |
| 551 } |
| 552 |
| 553 TEST_F(NTPSnippetsServiceTest, TestMultipleIncompleteSources) { |
| 554 // Set Source 2 to have no AMP url, and Source 1 to have no publisher name |
| 555 // Source 2 should win since we favor publisher name over amp url |
| 556 std::vector<std::string> source_urls, publishers, amp_urls; |
| 557 source_urls.push_back(std::string("http://source1.com")); |
| 558 source_urls.push_back(std::string("http://source2.com")); |
| 559 publishers.push_back(std::string()); |
| 560 publishers.push_back(std::string("Source 2")); |
| 561 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 562 amp_urls.push_back(std::string()); |
| 563 std::string json_str( |
| 564 GetTestJsonWithSources(source_urls, publishers, amp_urls)); |
| 565 |
| 566 LoadFromJSONString(json_str); |
| 567 EXPECT_EQ(service()->size(), 1u); |
| 568 |
| 569 for (auto& snippet : *service()) { |
| 570 EXPECT_EQ(snippet.sources().size(), 2u); |
| 571 EXPECT_EQ(snippet.url(), GURL("http://localhost/foobar")); |
| 572 EXPECT_EQ(snippet.best_source().url, GURL("http://source2.com")); |
| 573 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 2")); |
| 574 EXPECT_EQ(snippet.best_source().amp_url, GURL()); |
| 575 } |
| 576 |
| 577 service()->ClearSnippets(); |
| 578 // Set Source 1 to have no AMP url, and Source 2 to have no publisher name |
| 579 // Source 1 should win in this case since we prefer publisher name to AMP url |
| 580 source_urls.clear(); |
| 581 source_urls.push_back(std::string("http://source1.com")); |
| 582 source_urls.push_back(std::string("http://source2.com")); |
| 583 publishers.clear(); |
| 584 publishers.push_back(std::string("Source 1")); |
| 585 publishers.push_back(std::string()); |
| 586 amp_urls.clear(); |
| 587 amp_urls.push_back(std::string()); |
| 588 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 589 json_str = GetTestJsonWithSources(source_urls, publishers, amp_urls); |
| 590 |
| 591 LoadFromJSONString(json_str); |
| 592 EXPECT_EQ(service()->size(), 1u); |
| 593 |
| 594 for (auto& snippet : *service()) { |
| 595 EXPECT_EQ(snippet.sources().size(), 2u); |
| 596 EXPECT_EQ(snippet.url(), GURL("http://localhost/foobar")); |
| 597 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); |
| 598 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); |
| 599 EXPECT_EQ(snippet.best_source().amp_url, GURL()); |
| 600 } |
| 601 |
| 602 service()->ClearSnippets(); |
| 603 // Set source 1 to have no AMP url and no source, and source 2 to only have |
| 604 // amp url. There should be no snippets since we only add sources we consider |
| 605 // complete |
| 606 source_urls.clear(); |
| 607 source_urls.push_back(std::string("http://source1.com")); |
| 608 source_urls.push_back(std::string("http://source2.com")); |
| 609 publishers.clear(); |
| 610 publishers.push_back(std::string()); |
| 611 publishers.push_back(std::string()); |
| 612 amp_urls.clear(); |
| 613 amp_urls.push_back(std::string()); |
| 614 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 615 json_str = GetTestJsonWithSources(source_urls, publishers, amp_urls); |
| 616 |
| 617 LoadFromJSONString(json_str); |
| 618 EXPECT_EQ(service()->size(), 0u); |
| 619 } |
| 620 |
| 621 TEST_F(NTPSnippetsServiceTest, TestMultipleCompleteSources) { |
| 622 // Test 2 complete sources, we should choose the first complete source |
| 623 std::vector<std::string> source_urls, publishers, amp_urls; |
| 624 source_urls.push_back(std::string("http://source1.com")); |
| 625 source_urls.push_back(std::string("http://source2.com")); |
| 626 source_urls.push_back(std::string("http://source3.com")); |
| 627 publishers.push_back(std::string("Source 1")); |
| 628 publishers.push_back(std::string()); |
| 629 publishers.push_back(std::string("Source 3")); |
| 630 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 631 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 632 amp_urls.push_back(std::string("http://source3.amp.com")); |
| 633 std::string json_str( |
| 634 GetTestJsonWithSources(source_urls, publishers, amp_urls)); |
| 635 |
| 636 LoadFromJSONString(json_str); |
| 637 EXPECT_EQ(service()->size(), 1u); |
| 638 |
| 639 for (auto& snippet : *service()) { |
| 640 EXPECT_EQ(snippet.sources().size(), 3u); |
| 641 EXPECT_EQ(snippet.url(), GURL("http://localhost/foobar")); |
| 642 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); |
| 643 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); |
| 644 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source1.amp.com")); |
| 645 } |
| 646 |
| 647 // Test 2 complete sources, we should choose the first complete source |
| 648 service()->ClearSnippets(); |
| 649 source_urls.clear(); |
| 650 source_urls.push_back(std::string("http://source1.com")); |
| 651 source_urls.push_back(std::string("http://source2.com")); |
| 652 source_urls.push_back(std::string("http://source3.com")); |
| 653 publishers.clear(); |
| 654 publishers.push_back(std::string()); |
| 655 publishers.push_back(std::string("Source 2")); |
| 656 publishers.push_back(std::string("Source 3")); |
| 657 amp_urls.clear(); |
| 658 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 659 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 660 amp_urls.push_back(std::string("http://source3.amp.com")); |
| 661 json_str = GetTestJsonWithSources(source_urls, publishers, amp_urls); |
| 662 |
| 663 LoadFromJSONString(json_str); |
| 664 EXPECT_EQ(service()->size(), 1u); |
| 665 |
| 666 for (auto& snippet : *service()) { |
| 667 EXPECT_EQ(snippet.sources().size(), 3u); |
| 668 EXPECT_EQ(snippet.url(), GURL("http://localhost/foobar")); |
| 669 EXPECT_EQ(snippet.best_source().url, GURL("http://source2.com")); |
| 670 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 2")); |
| 671 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source2.amp.com")); |
| 672 } |
| 673 |
| 674 // Test 3 complete sources, we should choose the first complete source |
| 675 service()->ClearSnippets(); |
| 676 source_urls.clear(); |
| 677 source_urls.push_back(std::string("http://source1.com")); |
| 678 source_urls.push_back(std::string("http://source2.com")); |
| 679 source_urls.push_back(std::string("http://source3.com")); |
| 680 publishers.clear(); |
| 681 publishers.push_back(std::string("Source 1")); |
| 682 publishers.push_back(std::string("Source 2")); |
| 683 publishers.push_back(std::string("Source 3")); |
| 684 amp_urls.clear(); |
| 685 amp_urls.push_back(std::string()); |
| 686 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 687 amp_urls.push_back(std::string("http://source3.amp.com")); |
| 688 json_str = GetTestJsonWithSources(source_urls, publishers, amp_urls); |
| 689 |
| 690 LoadFromJSONString(json_str); |
| 691 EXPECT_EQ(service()->size(), 1u); |
| 692 |
| 693 for (auto& snippet : *service()) { |
| 694 EXPECT_EQ(snippet.sources().size(), 3u); |
| 695 EXPECT_EQ(snippet.url(), GURL("http://localhost/foobar")); |
| 696 EXPECT_EQ(snippet.best_source().url, GURL("http://source2.com")); |
| 697 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 2")); |
| 698 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source2.amp.com")); |
| 699 } |
| 700 } |
| 701 |
| 390 TEST_F(NTPSnippetsServiceTest, LogNumArticlesHistogram) { | 702 TEST_F(NTPSnippetsServiceTest, LogNumArticlesHistogram) { |
| 391 base::HistogramTester tester; | 703 base::HistogramTester tester; |
| 392 SetExpectJsonParseSuccess(false); | 704 SetExpectJsonParseSuccess(false); |
| 393 LoadFromJSONString(GetInvalidJson()); | 705 LoadFromJSONString(GetInvalidJson()); |
| 394 tester.ExpectUniqueSample("NewTabPage.Snippets.NumArticles", /*sample=*/0, | 706 tester.ExpectUniqueSample("NewTabPage.Snippets.NumArticles", /*sample=*/0, |
| 395 /*expected_count=*/1); | 707 /*expected_count=*/1); |
| 396 SetExpectJsonParseSuccess(true); | 708 SetExpectJsonParseSuccess(true); |
| 397 LoadFromJSONString(GetTestJson()); | 709 LoadFromJSONString(GetTestJson()); |
| 398 tester.ExpectBucketCount("NewTabPage.Snippets.NumArticles", /*sample=*/1, | 710 tester.ExpectBucketCount("NewTabPage.Snippets.NumArticles", /*sample=*/1, |
| 399 /*expected_count=*/1); | 711 /*expected_count=*/1); |
| 400 // Duplicate snippet shouldn't increase the list size. | 712 // Duplicate snippet shouldn't increase the list size. |
| 401 LoadFromJSONString(GetTestJson()); | 713 LoadFromJSONString(GetTestJson()); |
| 402 tester.ExpectBucketCount("NewTabPage.Snippets.NumArticles", /*sample=*/1, | 714 tester.ExpectBucketCount("NewTabPage.Snippets.NumArticles", /*sample=*/1, |
| 403 /*expected_count=*/2); | 715 /*expected_count=*/2); |
| 404 // Discarding a snippet should decrease the list size. This will only be | 716 // Discarding a snippet should decrease the list size. This will only be |
| 405 // logged after the next fetch. | 717 // logged after the next fetch. |
| 406 EXPECT_TRUE(service()->DiscardSnippet(GURL("http://localhost/foobar"))); | 718 EXPECT_TRUE(service()->DiscardSnippet(GURL("http://localhost/foobar"))); |
| 407 LoadFromJSONString(GetTestJson()); | 719 LoadFromJSONString(GetTestJson()); |
| 408 tester.ExpectBucketCount("NewTabPage.Snippets.NumArticles", /*sample=*/0, | 720 tester.ExpectBucketCount("NewTabPage.Snippets.NumArticles", /*sample=*/0, |
| 409 /*expected_count=*/2); | 721 /*expected_count=*/2); |
| 410 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticles", 4); | 722 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticles", 4); |
| 411 } | 723 } |
| 412 | |
| 413 } // namespace ntp_snippets | 724 } // namespace ntp_snippets |
| OLD | NEW |