| 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 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 namespace { | 46 namespace { |
| 47 | 47 |
| 48 MATCHER_P(IdEq, value, "") { | 48 MATCHER_P(IdEq, value, "") { |
| 49 return arg->id() == value; | 49 return arg->id() == value; |
| 50 } | 50 } |
| 51 | 51 |
| 52 const base::Time::Exploded kDefaultCreationTime = {2015, 11, 4, 25, 13, 46, 45}; | 52 const base::Time::Exploded kDefaultCreationTime = {2015, 11, 4, 25, 13, 46, 45}; |
| 53 const char kTestContentSnippetsServerFormat[] = | 53 const char kTestContentSnippetsServerFormat[] = |
| 54 "https://chromereader-pa.googleapis.com/v1/fetch?key=%s"; | 54 "https://chromereader-pa.googleapis.com/v1/fetch?key=%s"; |
| 55 | 55 |
| 56 const char kSnippetUrl[] = "http://localhost/foobar"; |
| 57 const char kSnippetTitle[] = "Title"; |
| 58 const char kSnippetText[] = "Snippet"; |
| 59 const char kSnippetSalientImage[] = "http://localhost/salient_image"; |
| 60 const char kSnippetPublisherName[] = "Foo News"; |
| 61 const char kSnippetAmpUrl[] = "http://localhost/amp"; |
| 62 const float kSnippetScore = 5.0; |
| 63 |
| 56 base::Time GetDefaultCreationTime() { | 64 base::Time GetDefaultCreationTime() { |
| 57 return base::Time::FromUTCExploded(kDefaultCreationTime); | 65 return base::Time::FromUTCExploded(kDefaultCreationTime); |
| 58 } | 66 } |
| 59 | 67 |
| 60 std::string GetTestJson(const std::string& content_creation_time_str, | 68 base::Time GetDefaultExpirationTime() { |
| 61 const std::string& expiry_time_str) { | 69 return base::Time::Now() + base::TimeDelta::FromHours(1); |
| 62 char json_str_format[] = | |
| 63 "{ \"recos\": [ " | |
| 64 "{ \"contentInfo\": {" | |
| 65 "\"url\" : \"http://localhost/foobar\"," | |
| 66 "\"title\" : \"Title\"," | |
| 67 "\"snippet\" : \"Snippet\"," | |
| 68 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," | |
| 69 "\"creationTimestampSec\" : \"%s\"," | |
| 70 "\"expiryTimestampSec\" : \"%s\"," | |
| 71 "\"sourceCorpusInfo\" : [ " | |
| 72 "{\"ampUrl\" : \"http://localhost/amp\"," | |
| 73 "\"corpusId\" : \"http://localhost/foobar\"," | |
| 74 "\"publisherData\": { \"sourceName\" : \"Foo News\"}}]" | |
| 75 "}}" | |
| 76 "]}"; | |
| 77 | |
| 78 return base::StringPrintf(json_str_format, content_creation_time_str.c_str(), | |
| 79 expiry_time_str.c_str()); | |
| 80 } | 70 } |
| 81 | 71 |
| 82 std::string GetTestJsonWithSources(const std::string& content_creation_time_str, | 72 std::string GetTestJson(const std::vector<std::string>& snippets) { |
| 83 const std::string& expiry_time_str, | 73 return base::StringPrintf("{\"recos\":[%s]}", |
| 84 const std::vector<std::string>& source_urls, | 74 base::JoinString(snippets, ", ").c_str()); |
| 85 const std::vector<std::string>& publishers, | 75 } |
| 86 const std::vector<std::string>& amp_urls) { | 76 |
| 77 std::string GetSnippetWithUrlAndTimesAndSources( |
| 78 const std::string& url, |
| 79 const std::string& content_creation_time_str, |
| 80 const std::string& expiry_time_str, |
| 81 const std::vector<std::string>& source_urls, |
| 82 const std::vector<std::string>& publishers, |
| 83 const std::vector<std::string>& amp_urls) { |
| 87 char json_str_format[] = | 84 char json_str_format[] = |
| 88 "{ \"recos\": [ " | |
| 89 "{ \"contentInfo\": {" | 85 "{ \"contentInfo\": {" |
| 90 "\"url\" : \"http://localhost/foobar\"," | 86 "\"url\" : \"%s\"," |
| 91 "\"title\" : \"Title\"," | 87 "\"title\" : \"%s\"," |
| 92 "\"snippet\" : \"Snippet\"," | 88 "\"snippet\" : \"%s\"," |
| 93 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," | 89 "\"thumbnailUrl\" : \"%s\"," |
| 94 "\"creationTimestampSec\" : \"%s\"," | 90 "\"creationTimestampSec\" : \"%s\"," |
| 95 "\"expiryTimestampSec\" : \"%s\"," | 91 "\"expiryTimestampSec\" : \"%s\"," |
| 96 "\"sourceCorpusInfo\" : [%s]" | 92 "\"sourceCorpusInfo\" : [%s]" |
| 97 "}}" | 93 "}, " |
| 98 "]}"; | 94 "\"score\" : %f}"; |
| 99 | 95 |
| 100 char source_corpus_info_format[] = | 96 char source_corpus_info_format[] = |
| 101 "{\"corpusId\": \"%s\"," | 97 "{\"corpusId\": \"%s\"," |
| 102 "\"publisherData\": {" | 98 "\"publisherData\": {" |
| 103 "\"sourceName\": \"%s\"" | 99 "\"sourceName\": \"%s\"" |
| 104 "}," | 100 "}," |
| 105 "\"ampUrl\": \"%s\"}"; | 101 "\"ampUrl\": \"%s\"}"; |
| 106 | 102 |
| 107 std::string source_corpus_info_list_str; | 103 std::string source_corpus_info_list_str; |
| 108 for (size_t i = 0; i < source_urls.size(); ++i) { | 104 for (size_t i = 0; i < source_urls.size(); ++i) { |
| 109 std::string source_corpus_info_str = | 105 std::string source_corpus_info_str = |
| 110 base::StringPrintf(source_corpus_info_format, | 106 base::StringPrintf(source_corpus_info_format, |
| 111 source_urls[i].empty() ? "" : source_urls[i].c_str(), | 107 source_urls[i].empty() ? "" : source_urls[i].c_str(), |
| 112 publishers[i].empty() ? "" : publishers[i].c_str(), | 108 publishers[i].empty() ? "" : publishers[i].c_str(), |
| 113 amp_urls[i].empty() ? "" : amp_urls[i].c_str()); | 109 amp_urls[i].empty() ? "" : amp_urls[i].c_str()); |
| 114 source_corpus_info_list_str.append(source_corpus_info_str); | 110 source_corpus_info_list_str.append(source_corpus_info_str); |
| 115 source_corpus_info_list_str.append(","); | 111 source_corpus_info_list_str.append(","); |
| 116 } | 112 } |
| 117 // Remove the last comma | 113 // Remove the last comma |
| 118 source_corpus_info_list_str.erase(source_corpus_info_list_str.size()-1, 1); | 114 source_corpus_info_list_str.erase(source_corpus_info_list_str.size()-1, 1); |
| 119 return base::StringPrintf(json_str_format, content_creation_time_str.c_str(), | 115 return base::StringPrintf(json_str_format, url.c_str(), kSnippetTitle, |
| 116 kSnippetText, kSnippetSalientImage, |
| 117 content_creation_time_str.c_str(), |
| 120 expiry_time_str.c_str(), | 118 expiry_time_str.c_str(), |
| 121 source_corpus_info_list_str.c_str()); | 119 source_corpus_info_list_str.c_str(), kSnippetScore); |
| 122 } | 120 } |
| 123 | 121 |
| 124 std::string GetTestJsonWithSources(const std::vector<std::string>& source_urls, | 122 std::string GetSnippetWithSources(const std::vector<std::string>& source_urls, |
| 125 const std::vector<std::string>& publishers, | 123 const std::vector<std::string>& publishers, |
| 126 const std::vector<std::string>& amp_urls) { | 124 const std::vector<std::string>& amp_urls) { |
| 127 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); | 125 return GetSnippetWithUrlAndTimesAndSources( |
| 128 return GetTestJsonWithSources( | 126 kSnippetUrl, NTPSnippet::TimeToJsonString(GetDefaultCreationTime()), |
| 129 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()), | 127 NTPSnippet::TimeToJsonString(GetDefaultExpirationTime()), source_urls, |
| 130 NTPSnippet::TimeToJsonString(expiry_time), source_urls, publishers, | 128 publishers, amp_urls); |
| 131 amp_urls); | |
| 132 } | 129 } |
| 133 | 130 |
| 134 std::string GetTestJson(const std::string& content_creation_time_str) { | 131 std::string GetSnippetWithUrlAndTimes( |
| 135 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); | 132 const std::string& url, |
| 136 return GetTestJson(content_creation_time_str, | 133 const std::string& content_creation_time_str, |
| 137 NTPSnippet::TimeToJsonString(expiry_time)); | 134 const std::string& expiry_time_str) { |
| 135 return GetSnippetWithUrlAndTimesAndSources( |
| 136 url, content_creation_time_str, expiry_time_str, |
| 137 {std::string(url)}, {std::string(kSnippetPublisherName)}, |
| 138 {std::string(kSnippetAmpUrl)}); |
| 138 } | 139 } |
| 139 | 140 |
| 140 std::string GetTestJson() { | 141 std::string GetSnippetWithTimes(const std::string& content_creation_time_str, |
| 141 return GetTestJson(NTPSnippet::TimeToJsonString(GetDefaultCreationTime())); | 142 const std::string& expiry_time_str) { |
| 143 return GetSnippetWithUrlAndTimes(kSnippetUrl, content_creation_time_str, |
| 144 expiry_time_str); |
| 142 } | 145 } |
| 143 | 146 |
| 144 std::string GetTestExpiredJson() { | 147 std::string GetSnippetWithUrl(const std::string& url) { |
| 145 return GetTestJson(NTPSnippet::TimeToJsonString(GetDefaultCreationTime()), | 148 return GetSnippetWithUrlAndTimes( |
| 146 NTPSnippet::TimeToJsonString(base::Time::Now())); | 149 url, NTPSnippet::TimeToJsonString(GetDefaultCreationTime()), |
| 150 NTPSnippet::TimeToJsonString(GetDefaultExpirationTime())); |
| 147 } | 151 } |
| 148 | 152 |
| 149 std::string GetInvalidJson() { | 153 std::string GetSnippet() { |
| 150 std::string json_str = GetTestJson(); | 154 return GetSnippetWithUrlAndTimes( |
| 155 kSnippetUrl, NTPSnippet::TimeToJsonString(GetDefaultCreationTime()), |
| 156 NTPSnippet::TimeToJsonString(GetDefaultExpirationTime())); |
| 157 } |
| 158 |
| 159 std::string GetExpiredSnippet() { |
| 160 return GetSnippetWithTimes( |
| 161 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()), |
| 162 NTPSnippet::TimeToJsonString(base::Time::Now())); |
| 163 } |
| 164 |
| 165 std::string GetInvalidSnippet() { |
| 166 std::string json_str = GetSnippet(); |
| 151 // Make the json invalid by removing the final closing brace. | 167 // Make the json invalid by removing the final closing brace. |
| 152 return json_str.substr(0, json_str.size() - 1); | 168 return json_str.substr(0, json_str.size() - 1); |
| 153 } | 169 } |
| 154 | 170 |
| 155 std::string GetIncompleteJson() { | 171 std::string GetIncompleteSnippet() { |
| 156 std::string json_str = GetTestJson(); | 172 std::string json_str = GetSnippet(); |
| 157 // Rename the "url" entry. The result is syntactically valid json that will | 173 // Rename the "url" entry. The result is syntactically valid json that will |
| 158 // fail to parse as snippets. | 174 // fail to parse as snippets. |
| 159 size_t pos = json_str.find("\"url\""); | 175 size_t pos = json_str.find("\"url\""); |
| 160 if (pos == std::string::npos) { | 176 if (pos == std::string::npos) { |
| 161 NOTREACHED(); | 177 NOTREACHED(); |
| 162 return std::string(); | 178 return std::string(); |
| 163 } | 179 } |
| 164 json_str[pos + 1] = 'x'; | 180 json_str[pos + 1] = 'x'; |
| 165 return json_str; | 181 return json_str; |
| 166 } | 182 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 | 307 |
| 292 TEST_F(NTPSnippetsServiceTest, ScheduleIfEnabled) { | 308 TEST_F(NTPSnippetsServiceTest, ScheduleIfEnabled) { |
| 293 // SetUp() checks that Schedule is called. | 309 // SetUp() checks that Schedule is called. |
| 294 } | 310 } |
| 295 | 311 |
| 296 TEST_F(NTPSnippetsServiceDisabledTest, Unschedule) { | 312 TEST_F(NTPSnippetsServiceDisabledTest, Unschedule) { |
| 297 // SetUp() checks that Unschedule is called. | 313 // SetUp() checks that Unschedule is called. |
| 298 } | 314 } |
| 299 | 315 |
| 300 TEST_F(NTPSnippetsServiceTest, Full) { | 316 TEST_F(NTPSnippetsServiceTest, Full) { |
| 301 std::string json_str(GetTestJson()); | 317 std::string json_str(GetTestJson({GetSnippet()})); |
| 302 | 318 |
| 303 LoadFromJSONString(json_str); | 319 LoadFromJSONString(json_str); |
| 304 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 320 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 305 const NTPSnippet& snippet = *service()->snippets().front(); | 321 const NTPSnippet& snippet = *service()->snippets().front(); |
| 306 EXPECT_EQ(snippet.id(), "http://localhost/foobar"); | 322 |
| 307 EXPECT_EQ(snippet.best_source().publisher_name, "Foo News"); | 323 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 308 EXPECT_EQ(snippet.title(), "Title"); | 324 EXPECT_EQ(snippet.title(), kSnippetTitle); |
| 309 EXPECT_EQ(snippet.snippet(), "Snippet"); | 325 EXPECT_EQ(snippet.snippet(), kSnippetText); |
| 310 EXPECT_EQ(snippet.salient_image_url(), | 326 EXPECT_EQ(snippet.salient_image_url(), GURL(kSnippetSalientImage)); |
| 311 GURL("http://localhost/salient_image")); | |
| 312 EXPECT_EQ(GetDefaultCreationTime(), snippet.publish_date()); | 327 EXPECT_EQ(GetDefaultCreationTime(), snippet.publish_date()); |
| 313 EXPECT_EQ(snippet.best_source().amp_url.spec(), | 328 EXPECT_EQ(snippet.best_source().publisher_name, kSnippetPublisherName); |
| 314 GURL("http://localhost/amp").spec()); | 329 EXPECT_EQ(snippet.best_source().amp_url, GURL(kSnippetAmpUrl)); |
| 315 } | 330 } |
| 316 | 331 |
| 317 TEST_F(NTPSnippetsServiceTest, Clear) { | 332 TEST_F(NTPSnippetsServiceTest, Clear) { |
| 318 std::string json_str(GetTestJson()); | 333 std::string json_str(GetTestJson({GetSnippet()})); |
| 319 | 334 |
| 320 LoadFromJSONString(json_str); | 335 LoadFromJSONString(json_str); |
| 321 EXPECT_THAT(service()->snippets(), SizeIs(1)); | 336 EXPECT_THAT(service()->snippets(), SizeIs(1)); |
| 322 | 337 |
| 323 service()->ClearSnippets(); | 338 service()->ClearSnippets(); |
| 324 EXPECT_THAT(service()->snippets(), IsEmpty()); | 339 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 325 } | 340 } |
| 326 | 341 |
| 327 TEST_F(NTPSnippetsServiceTest, InsertAtFront) { | 342 TEST_F(NTPSnippetsServiceTest, InsertAtFront) { |
| 328 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); | 343 std::string first("http://first"); |
| 329 char json_str_format[] = | 344 LoadFromJSONString(GetTestJson({GetSnippetWithUrl(first)})); |
| 330 "{ \"recos\": [ " | 345 EXPECT_THAT(service()->snippets(), ElementsAre(IdEq(first))); |
| 331 "{ \"contentInfo\": {" | |
| 332 "\"url\" : \"%s\"," | |
| 333 "\"title\" : \"Title\"," | |
| 334 "\"snippet\" : \"Snippet\"," | |
| 335 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," | |
| 336 "\"creationTimestampSec\" : \"%s\"," | |
| 337 "\"expiryTimestampSec\" : \"%s\"," | |
| 338 "\"sourceCorpusInfo\" : [{\"corpusId\": \"%s\"," | |
| 339 "\"publisherData\": {" | |
| 340 "\"sourceName\": \"Source 1\"" | |
| 341 "}," | |
| 342 "\"ampUrl\": \"\"}]" | |
| 343 "}}" | |
| 344 "]}"; | |
| 345 const std::string first_url = "http://first"; | |
| 346 std::string json_str(base::StringPrintf( | |
| 347 json_str_format, first_url.c_str(), | |
| 348 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | |
| 349 NTPSnippet::TimeToJsonString(expiry_time).c_str(), first_url.c_str())); | |
| 350 | 346 |
| 351 LoadFromJSONString(json_str); | 347 std::string second("http://second"); |
| 352 | 348 LoadFromJSONString(GetTestJson({GetSnippetWithUrl(second)})); |
| 353 EXPECT_THAT(service()->snippets(), ElementsAre(IdEq(first_url))); | |
| 354 | |
| 355 const std::string second_url = "http://second"; | |
| 356 json_str = base::StringPrintf( | |
| 357 json_str_format, second_url.c_str(), | |
| 358 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | |
| 359 NTPSnippet::TimeToJsonString(expiry_time).c_str(), second_url.c_str()); | |
| 360 | |
| 361 LoadFromJSONString(json_str); | |
| 362 | |
| 363 // The snippet loaded last should be at the first position in the list now. | 349 // The snippet loaded last should be at the first position in the list now. |
| 364 EXPECT_THAT(service()->snippets(), | 350 EXPECT_THAT(service()->snippets(), ElementsAre(IdEq(second), IdEq(first))); |
| 365 ElementsAre(IdEq(second_url), IdEq(first_url))); | |
| 366 } | 351 } |
| 367 | 352 |
| 368 TEST_F(NTPSnippetsServiceTest, LimitNumSnippets) { | 353 TEST_F(NTPSnippetsServiceTest, LimitNumSnippets) { |
| 369 int max_snippet_count = NTPSnippetsService::GetMaxSnippetCountForTesting(); | 354 int max_snippet_count = NTPSnippetsService::GetMaxSnippetCountForTesting(); |
| 370 int snippets_per_load = max_snippet_count / 2 + 1; | 355 int snippets_per_load = max_snippet_count / 2 + 1; |
| 371 | 356 char url_format[] = "http://localhost/%i"; |
| 372 base::Time expiry_time = base::Time::Now() + base::TimeDelta::FromHours(1); | |
| 373 char json_str_format[] = | |
| 374 "{ \"contentInfo\": {" | |
| 375 "\"url\" : \"http://localhost/%i\"," | |
| 376 "\"title\" : \"Title\"," | |
| 377 "\"snippet\" : \"Snippet\"," | |
| 378 "\"thumbnailUrl\" : \"http://localhost/salient_image\"," | |
| 379 "\"creationTimestampSec\" : \"%s\"," | |
| 380 "\"expiryTimestampSec\" : \"%s\"," | |
| 381 "\"sourceCorpusInfo\" : [{\"corpusId\": \"http://localhost/%i\"," | |
| 382 "\"publisherData\": {" | |
| 383 "\"sourceName\": \"Source 1\"" | |
| 384 "}," | |
| 385 "\"ampUrl\": \"\"}]" | |
| 386 "}}"; | |
| 387 | 357 |
| 388 std::vector<std::string> snippets1; | 358 std::vector<std::string> snippets1; |
| 389 std::vector<std::string> snippets2; | 359 std::vector<std::string> snippets2; |
| 390 for (int i = 0; i < snippets_per_load; i++) { | 360 for (int i = 0; i < snippets_per_load; i++) { |
| 391 snippets1.push_back(base::StringPrintf( | 361 snippets1.push_back(GetSnippetWithUrl(base::StringPrintf(url_format, i))); |
| 392 json_str_format, i, | 362 snippets2.push_back(GetSnippetWithUrl( |
| 393 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | 363 base::StringPrintf(url_format, snippets_per_load + i))); |
| 394 NTPSnippet::TimeToJsonString(expiry_time).c_str(), i /* for corpusId */ | |
| 395 )); | |
| 396 snippets2.push_back(base::StringPrintf( | |
| 397 json_str_format, snippets_per_load + i, | |
| 398 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | |
| 399 NTPSnippet::TimeToJsonString(expiry_time).c_str(), | |
| 400 snippets_per_load + i /* for corpusId */)); | |
| 401 } | 364 } |
| 402 | 365 |
| 403 LoadFromJSONString( | 366 LoadFromJSONString(GetTestJson(snippets1)); |
| 404 "{ \"recos\": [ " + base::JoinString(snippets1, ", ") + "]}"); | |
| 405 ASSERT_THAT(service()->snippets(), SizeIs(snippets1.size())); | 367 ASSERT_THAT(service()->snippets(), SizeIs(snippets1.size())); |
| 406 | 368 |
| 407 LoadFromJSONString( | 369 LoadFromJSONString(GetTestJson(snippets2)); |
| 408 "{ \"recos\": [ " + base::JoinString(snippets2, ", ") + "]}"); | |
| 409 EXPECT_THAT(service()->snippets(), SizeIs(max_snippet_count)); | 370 EXPECT_THAT(service()->snippets(), SizeIs(max_snippet_count)); |
| 410 } | 371 } |
| 411 | 372 |
| 412 TEST_F(NTPSnippetsServiceTest, LoadInvalidJson) { | 373 TEST_F(NTPSnippetsServiceTest, LoadInvalidJson) { |
| 413 LoadFromJSONString(GetInvalidJson()); | 374 LoadFromJSONString(GetTestJson({GetInvalidSnippet()})); |
| 414 EXPECT_THAT(service()->snippets_fetcher()->last_status(), | 375 EXPECT_THAT(service()->snippets_fetcher()->last_status(), |
| 415 StartsWith("Received invalid JSON")); | 376 StartsWith("Received invalid JSON")); |
| 416 EXPECT_THAT(service()->snippets(), IsEmpty()); | 377 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 417 } | 378 } |
| 418 | 379 |
| 419 TEST_F(NTPSnippetsServiceTest, LoadInvalidJsonWithExistingSnippets) { | 380 TEST_F(NTPSnippetsServiceTest, LoadInvalidJsonWithExistingSnippets) { |
| 420 LoadFromJSONString(GetTestJson()); | 381 LoadFromJSONString(GetTestJson({GetSnippet()})); |
| 421 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 382 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 422 ASSERT_EQ("OK", service()->snippets_fetcher()->last_status()); | 383 ASSERT_EQ("OK", service()->snippets_fetcher()->last_status()); |
| 423 | 384 |
| 424 LoadFromJSONString(GetInvalidJson()); | 385 LoadFromJSONString(GetTestJson({GetInvalidSnippet()})); |
| 425 EXPECT_THAT(service()->snippets_fetcher()->last_status(), | 386 EXPECT_THAT(service()->snippets_fetcher()->last_status(), |
| 426 StartsWith("Received invalid JSON")); | 387 StartsWith("Received invalid JSON")); |
| 427 // This should not have changed the existing snippets. | 388 // This should not have changed the existing snippets. |
| 428 EXPECT_THAT(service()->snippets(), SizeIs(1)); | 389 EXPECT_THAT(service()->snippets(), SizeIs(1)); |
| 429 } | 390 } |
| 430 | 391 |
| 431 TEST_F(NTPSnippetsServiceTest, LoadIncompleteJson) { | 392 TEST_F(NTPSnippetsServiceTest, LoadIncompleteJson) { |
| 432 LoadFromJSONString(GetIncompleteJson()); | 393 LoadFromJSONString(GetTestJson({GetIncompleteSnippet()})); |
| 433 EXPECT_EQ("Invalid / empty list.", | 394 EXPECT_EQ("Invalid / empty list.", |
| 434 service()->snippets_fetcher()->last_status()); | 395 service()->snippets_fetcher()->last_status()); |
| 435 EXPECT_THAT(service()->snippets(), IsEmpty()); | 396 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 436 } | 397 } |
| 437 | 398 |
| 438 TEST_F(NTPSnippetsServiceTest, LoadIncompleteJsonWithExistingSnippets) { | 399 TEST_F(NTPSnippetsServiceTest, LoadIncompleteJsonWithExistingSnippets) { |
| 439 LoadFromJSONString(GetTestJson()); | 400 LoadFromJSONString(GetTestJson({GetSnippet()})); |
| 440 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 401 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 441 | 402 |
| 442 LoadFromJSONString(GetIncompleteJson()); | 403 LoadFromJSONString(GetTestJson({GetIncompleteSnippet()})); |
| 443 EXPECT_EQ("Invalid / empty list.", | 404 EXPECT_EQ("Invalid / empty list.", |
| 444 service()->snippets_fetcher()->last_status()); | 405 service()->snippets_fetcher()->last_status()); |
| 445 // This should not have changed the existing snippets. | 406 // This should not have changed the existing snippets. |
| 446 EXPECT_THAT(service()->snippets(), SizeIs(1)); | 407 EXPECT_THAT(service()->snippets(), SizeIs(1)); |
| 447 } | 408 } |
| 448 | 409 |
| 449 TEST_F(NTPSnippetsServiceTest, Discard) { | 410 TEST_F(NTPSnippetsServiceTest, Discard) { |
| 450 std::vector<std::string> source_urls, publishers, amp_urls; | 411 std::vector<std::string> source_urls, publishers, amp_urls; |
| 451 source_urls.push_back(std::string("http://site.com")); | 412 source_urls.push_back(std::string("http://site.com")); |
| 452 publishers.push_back(std::string("Source 1")); | 413 publishers.push_back(std::string("Source 1")); |
| 453 amp_urls.push_back(std::string()); | 414 amp_urls.push_back(std::string()); |
| 454 std::string json_str( | 415 std::string json_str( |
| 455 GetTestJsonWithSources(source_urls, publishers, amp_urls)); | 416 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)})); |
| 456 | 417 |
| 457 LoadFromJSONString(json_str); | 418 LoadFromJSONString(json_str); |
| 458 | 419 |
| 459 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 420 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 460 | 421 |
| 461 // Discarding a non-existent snippet shouldn't do anything. | 422 // Discarding a non-existent snippet shouldn't do anything. |
| 462 EXPECT_FALSE(service()->DiscardSnippet("http://othersite.com")); | 423 EXPECT_FALSE(service()->DiscardSnippet("http://othersite.com")); |
| 463 EXPECT_THAT(service()->snippets(), SizeIs(1)); | 424 EXPECT_THAT(service()->snippets(), SizeIs(1)); |
| 464 | 425 |
| 465 // Discard the snippet. | 426 // Discard the snippet. |
| 466 EXPECT_TRUE(service()->DiscardSnippet("http://localhost/foobar")); | 427 EXPECT_TRUE(service()->DiscardSnippet(kSnippetUrl)); |
| 467 EXPECT_THAT(service()->snippets(), IsEmpty()); | 428 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 468 | 429 |
| 469 // Make sure that fetching the same snippet again does not re-add it. | 430 // Make sure that fetching the same snippet again does not re-add it. |
| 470 LoadFromJSONString(json_str); | 431 LoadFromJSONString(json_str); |
| 471 EXPECT_THAT(service()->snippets(), IsEmpty()); | 432 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 472 | 433 |
| 473 // The snippet should stay discarded even after re-creating the service. | 434 // The snippet should stay discarded even after re-creating the service. |
| 474 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); | 435 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); |
| 475 CreateSnippetsService(/*enabled=*/true); | 436 CreateSnippetsService(/*enabled=*/true); |
| 476 LoadFromJSONString(json_str); | 437 LoadFromJSONString(json_str); |
| 477 EXPECT_THAT(service()->snippets(), IsEmpty()); | 438 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 478 | 439 |
| 479 // The snippet can be added again after clearing discarded snippets. | 440 // The snippet can be added again after clearing discarded snippets. |
| 480 service()->ClearDiscardedSnippets(); | 441 service()->ClearDiscardedSnippets(); |
| 481 EXPECT_THAT(service()->snippets(), IsEmpty()); | 442 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 482 LoadFromJSONString(json_str); | 443 LoadFromJSONString(json_str); |
| 483 EXPECT_THAT(service()->snippets(), SizeIs(1)); | 444 EXPECT_THAT(service()->snippets(), SizeIs(1)); |
| 484 } | 445 } |
| 485 | 446 |
| 486 TEST_F(NTPSnippetsServiceTest, GetDiscarded) { | 447 TEST_F(NTPSnippetsServiceTest, GetDiscarded) { |
| 487 LoadFromJSONString(GetTestJson()); | 448 LoadFromJSONString(GetTestJson({GetSnippet()})); |
| 488 | 449 |
| 489 // For the test, we need the snippet to get discarded. | 450 // For the test, we need the snippet to get discarded. |
| 490 ASSERT_TRUE(service()->DiscardSnippet("http://localhost/foobar")); | 451 ASSERT_TRUE(service()->DiscardSnippet(kSnippetUrl)); |
| 491 const NTPSnippet::PtrVector& snippets = service()->discarded_snippets(); | 452 const NTPSnippet::PtrVector& snippets = service()->discarded_snippets(); |
| 492 EXPECT_EQ(1u, snippets.size()); | 453 EXPECT_EQ(1u, snippets.size()); |
| 493 for (auto& snippet : snippets) { | 454 for (auto& snippet : snippets) { |
| 494 EXPECT_EQ("http://localhost/foobar", snippet->id()); | 455 EXPECT_EQ(kSnippetUrl, snippet->id()); |
| 495 } | 456 } |
| 496 | 457 |
| 497 // There should be no discarded snippet after clearing the list. | 458 // There should be no discarded snippet after clearing the list. |
| 498 service()->ClearDiscardedSnippets(); | 459 service()->ClearDiscardedSnippets(); |
| 499 EXPECT_EQ(0u, service()->discarded_snippets().size()); | 460 EXPECT_EQ(0u, service()->discarded_snippets().size()); |
| 500 } | 461 } |
| 501 | 462 |
| 502 TEST_F(NTPSnippetsServiceTest, CreationTimestampParseFail) { | 463 TEST_F(NTPSnippetsServiceTest, CreationTimestampParseFail) { |
| 503 std::string json_str(GetTestJson("aaa1448459205")); | 464 std::string json_str(GetTestJson({GetSnippetWithTimes( |
| 465 "aaa1448459205", |
| 466 NTPSnippet::TimeToJsonString(GetDefaultExpirationTime()))})); |
| 504 | 467 |
| 505 LoadFromJSONString(json_str); | 468 LoadFromJSONString(json_str); |
| 506 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 469 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 507 const NTPSnippet& snippet = *service()->snippets().front(); | 470 const NTPSnippet& snippet = *service()->snippets().front(); |
| 508 EXPECT_EQ(snippet.id(), "http://localhost/foobar"); | 471 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 509 EXPECT_EQ(snippet.title(), "Title"); | 472 EXPECT_EQ(snippet.title(), kSnippetTitle); |
| 510 EXPECT_EQ(snippet.snippet(), "Snippet"); | 473 EXPECT_EQ(snippet.snippet(), kSnippetText); |
| 511 EXPECT_EQ(base::Time::UnixEpoch(), snippet.publish_date()); | 474 EXPECT_EQ(base::Time::UnixEpoch(), snippet.publish_date()); |
| 512 } | 475 } |
| 513 | 476 |
| 514 TEST_F(NTPSnippetsServiceTest, RemoveExpiredContent) { | 477 TEST_F(NTPSnippetsServiceTest, RemoveExpiredContent) { |
| 515 std::string json_str(GetTestExpiredJson()); | 478 std::string json_str(GetTestJson({GetExpiredSnippet()})); |
| 516 | 479 |
| 517 LoadFromJSONString(json_str); | 480 LoadFromJSONString(json_str); |
| 518 EXPECT_THAT(service()->snippets(), IsEmpty()); | 481 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 519 } | 482 } |
| 520 | 483 |
| 521 TEST_F(NTPSnippetsServiceTest, TestSingleSource) { | 484 TEST_F(NTPSnippetsServiceTest, TestSingleSource) { |
| 522 std::vector<std::string> source_urls, publishers, amp_urls; | 485 std::vector<std::string> source_urls, publishers, amp_urls; |
| 523 source_urls.push_back(std::string("http://source1.com")); | 486 source_urls.push_back(std::string("http://source1.com")); |
| 524 publishers.push_back(std::string("Source 1")); | 487 publishers.push_back(std::string("Source 1")); |
| 525 amp_urls.push_back(std::string("http://source1.amp.com")); | 488 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 526 std::string json_str( | 489 std::string json_str( |
| 527 GetTestJsonWithSources(source_urls, publishers, amp_urls)); | 490 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)})); |
| 528 | 491 |
| 529 LoadFromJSONString(json_str); | 492 LoadFromJSONString(json_str); |
| 530 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 493 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 531 const NTPSnippet& snippet = *service()->snippets().front(); | 494 const NTPSnippet& snippet = *service()->snippets().front(); |
| 532 EXPECT_EQ(snippet.sources().size(), 1u); | 495 EXPECT_EQ(snippet.sources().size(), 1u); |
| 533 EXPECT_EQ(snippet.id(), "http://localhost/foobar"); | 496 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 534 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); | 497 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); |
| 535 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); | 498 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); |
| 536 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source1.amp.com")); | 499 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source1.amp.com")); |
| 537 } | 500 } |
| 538 | 501 |
| 539 TEST_F(NTPSnippetsServiceTest, TestSingleSourceWithMalformedUrl) { | 502 TEST_F(NTPSnippetsServiceTest, TestSingleSourceWithMalformedUrl) { |
| 540 std::vector<std::string> source_urls, publishers, amp_urls; | 503 std::vector<std::string> source_urls, publishers, amp_urls; |
| 541 source_urls.push_back(std::string("aaaa")); | 504 source_urls.push_back(std::string("aaaa")); |
| 542 publishers.push_back(std::string("Source 1")); | 505 publishers.push_back(std::string("Source 1")); |
| 543 amp_urls.push_back(std::string("http://source1.amp.com")); | 506 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 544 std::string json_str( | 507 std::string json_str( |
| 545 GetTestJsonWithSources(source_urls, publishers, amp_urls)); | 508 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)})); |
| 546 | 509 |
| 547 LoadFromJSONString(json_str); | 510 LoadFromJSONString(json_str); |
| 548 EXPECT_THAT(service()->snippets(), IsEmpty()); | 511 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 549 } | 512 } |
| 550 | 513 |
| 551 TEST_F(NTPSnippetsServiceTest, TestSingleSourceWithMissingData) { | 514 TEST_F(NTPSnippetsServiceTest, TestSingleSourceWithMissingData) { |
| 552 std::vector<std::string> source_urls, publishers, amp_urls; | 515 std::vector<std::string> source_urls, publishers, amp_urls; |
| 553 source_urls.push_back(std::string("http://source1.com")); | 516 source_urls.push_back(std::string("http://source1.com")); |
| 554 publishers.push_back(std::string()); | 517 publishers.push_back(std::string()); |
| 555 amp_urls.push_back(std::string()); | 518 amp_urls.push_back(std::string()); |
| 556 std::string json_str( | 519 std::string json_str( |
| 557 GetTestJsonWithSources(source_urls, publishers, amp_urls)); | 520 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)})); |
| 558 | 521 |
| 559 LoadFromJSONString(json_str); | 522 LoadFromJSONString(json_str); |
| 560 EXPECT_THAT(service()->snippets(), IsEmpty()); | 523 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 561 } | 524 } |
| 562 | 525 |
| 563 TEST_F(NTPSnippetsServiceTest, TestMultipleSources) { | 526 TEST_F(NTPSnippetsServiceTest, TestMultipleSources) { |
| 564 std::vector<std::string> source_urls, publishers, amp_urls; | 527 std::vector<std::string> source_urls, publishers, amp_urls; |
| 565 source_urls.push_back(std::string("http://source1.com")); | 528 source_urls.push_back(std::string("http://source1.com")); |
| 566 source_urls.push_back(std::string("http://source2.com")); | 529 source_urls.push_back(std::string("http://source2.com")); |
| 567 publishers.push_back(std::string("Source 1")); | 530 publishers.push_back(std::string("Source 1")); |
| 568 publishers.push_back(std::string("Source 2")); | 531 publishers.push_back(std::string("Source 2")); |
| 569 amp_urls.push_back(std::string("http://source1.amp.com")); | 532 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 570 amp_urls.push_back(std::string("http://source2.amp.com")); | 533 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 571 std::string json_str( | 534 std::string json_str( |
| 572 GetTestJsonWithSources(source_urls, publishers, amp_urls)); | 535 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)})); |
| 573 | 536 |
| 574 LoadFromJSONString(json_str); | 537 LoadFromJSONString(json_str); |
| 575 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 538 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 576 const NTPSnippet& snippet = *service()->snippets().front(); | 539 const NTPSnippet& snippet = *service()->snippets().front(); |
| 577 // Expect the first source to be chosen | 540 // Expect the first source to be chosen |
| 578 EXPECT_EQ(snippet.sources().size(), 2u); | 541 EXPECT_EQ(snippet.sources().size(), 2u); |
| 579 EXPECT_EQ(snippet.id(), "http://localhost/foobar"); | 542 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 580 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); | 543 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); |
| 581 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); | 544 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); |
| 582 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source1.amp.com")); | 545 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source1.amp.com")); |
| 583 } | 546 } |
| 584 | 547 |
| 585 TEST_F(NTPSnippetsServiceTest, TestMultipleIncompleteSources) { | 548 TEST_F(NTPSnippetsServiceTest, TestMultipleIncompleteSources) { |
| 586 // Set Source 2 to have no AMP url, and Source 1 to have no publisher name | 549 // Set Source 2 to have no AMP url, and Source 1 to have no publisher name |
| 587 // Source 2 should win since we favor publisher name over amp url | 550 // Source 2 should win since we favor publisher name over amp url |
| 588 std::vector<std::string> source_urls, publishers, amp_urls; | 551 std::vector<std::string> source_urls, publishers, amp_urls; |
| 589 source_urls.push_back(std::string("http://source1.com")); | 552 source_urls.push_back(std::string("http://source1.com")); |
| 590 source_urls.push_back(std::string("http://source2.com")); | 553 source_urls.push_back(std::string("http://source2.com")); |
| 591 publishers.push_back(std::string()); | 554 publishers.push_back(std::string()); |
| 592 publishers.push_back(std::string("Source 2")); | 555 publishers.push_back(std::string("Source 2")); |
| 593 amp_urls.push_back(std::string("http://source1.amp.com")); | 556 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 594 amp_urls.push_back(std::string()); | 557 amp_urls.push_back(std::string()); |
| 595 std::string json_str( | 558 std::string json_str( |
| 596 GetTestJsonWithSources(source_urls, publishers, amp_urls)); | 559 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)})); |
| 597 | 560 |
| 598 LoadFromJSONString(json_str); | 561 LoadFromJSONString(json_str); |
| 599 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 562 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 600 { | 563 { |
| 601 const NTPSnippet& snippet = *service()->snippets().front(); | 564 const NTPSnippet& snippet = *service()->snippets().front(); |
| 602 EXPECT_EQ(snippet.sources().size(), 2u); | 565 EXPECT_EQ(snippet.sources().size(), 2u); |
| 603 EXPECT_EQ(snippet.id(), "http://localhost/foobar"); | 566 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 604 EXPECT_EQ(snippet.best_source().url, GURL("http://source2.com")); | 567 EXPECT_EQ(snippet.best_source().url, GURL("http://source2.com")); |
| 605 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 2")); | 568 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 2")); |
| 606 EXPECT_EQ(snippet.best_source().amp_url, GURL()); | 569 EXPECT_EQ(snippet.best_source().amp_url, GURL()); |
| 607 } | 570 } |
| 608 | 571 |
| 609 service()->ClearSnippets(); | 572 service()->ClearSnippets(); |
| 610 // Set Source 1 to have no AMP url, and Source 2 to have no publisher name | 573 // Set Source 1 to have no AMP url, and Source 2 to have no publisher name |
| 611 // Source 1 should win in this case since we prefer publisher name to AMP url | 574 // Source 1 should win in this case since we prefer publisher name to AMP url |
| 612 source_urls.clear(); | 575 source_urls.clear(); |
| 613 source_urls.push_back(std::string("http://source1.com")); | 576 source_urls.push_back(std::string("http://source1.com")); |
| 614 source_urls.push_back(std::string("http://source2.com")); | 577 source_urls.push_back(std::string("http://source2.com")); |
| 615 publishers.clear(); | 578 publishers.clear(); |
| 616 publishers.push_back(std::string("Source 1")); | 579 publishers.push_back(std::string("Source 1")); |
| 617 publishers.push_back(std::string()); | 580 publishers.push_back(std::string()); |
| 618 amp_urls.clear(); | 581 amp_urls.clear(); |
| 619 amp_urls.push_back(std::string()); | 582 amp_urls.push_back(std::string()); |
| 620 amp_urls.push_back(std::string("http://source2.amp.com")); | 583 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 621 json_str = GetTestJsonWithSources(source_urls, publishers, amp_urls); | 584 json_str = |
| 585 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)}); |
| 622 | 586 |
| 623 LoadFromJSONString(json_str); | 587 LoadFromJSONString(json_str); |
| 624 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 588 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 625 { | 589 { |
| 626 const NTPSnippet& snippet = *service()->snippets().front(); | 590 const NTPSnippet& snippet = *service()->snippets().front(); |
| 627 EXPECT_EQ(snippet.sources().size(), 2u); | 591 EXPECT_EQ(snippet.sources().size(), 2u); |
| 628 EXPECT_EQ(snippet.id(), "http://localhost/foobar"); | 592 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 629 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); | 593 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); |
| 630 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); | 594 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); |
| 631 EXPECT_EQ(snippet.best_source().amp_url, GURL()); | 595 EXPECT_EQ(snippet.best_source().amp_url, GURL()); |
| 632 } | 596 } |
| 633 | 597 |
| 634 service()->ClearSnippets(); | 598 service()->ClearSnippets(); |
| 635 // Set source 1 to have no AMP url and no source, and source 2 to only have | 599 // Set source 1 to have no AMP url and no source, and source 2 to only have |
| 636 // amp url. There should be no snippets since we only add sources we consider | 600 // amp url. There should be no snippets since we only add sources we consider |
| 637 // complete | 601 // complete |
| 638 source_urls.clear(); | 602 source_urls.clear(); |
| 639 source_urls.push_back(std::string("http://source1.com")); | 603 source_urls.push_back(std::string("http://source1.com")); |
| 640 source_urls.push_back(std::string("http://source2.com")); | 604 source_urls.push_back(std::string("http://source2.com")); |
| 641 publishers.clear(); | 605 publishers.clear(); |
| 642 publishers.push_back(std::string()); | 606 publishers.push_back(std::string()); |
| 643 publishers.push_back(std::string()); | 607 publishers.push_back(std::string()); |
| 644 amp_urls.clear(); | 608 amp_urls.clear(); |
| 645 amp_urls.push_back(std::string()); | 609 amp_urls.push_back(std::string()); |
| 646 amp_urls.push_back(std::string("http://source2.amp.com")); | 610 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 647 json_str = GetTestJsonWithSources(source_urls, publishers, amp_urls); | 611 json_str = |
| 612 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)}); |
| 648 | 613 |
| 649 LoadFromJSONString(json_str); | 614 LoadFromJSONString(json_str); |
| 650 EXPECT_THAT(service()->snippets(), IsEmpty()); | 615 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 651 } | 616 } |
| 652 | 617 |
| 653 TEST_F(NTPSnippetsServiceTest, TestMultipleCompleteSources) { | 618 TEST_F(NTPSnippetsServiceTest, TestMultipleCompleteSources) { |
| 654 // Test 2 complete sources, we should choose the first complete source | 619 // Test 2 complete sources, we should choose the first complete source |
| 655 std::vector<std::string> source_urls, publishers, amp_urls; | 620 std::vector<std::string> source_urls, publishers, amp_urls; |
| 656 source_urls.push_back(std::string("http://source1.com")); | 621 source_urls.push_back(std::string("http://source1.com")); |
| 657 source_urls.push_back(std::string("http://source2.com")); | 622 source_urls.push_back(std::string("http://source2.com")); |
| 658 source_urls.push_back(std::string("http://source3.com")); | 623 source_urls.push_back(std::string("http://source3.com")); |
| 659 publishers.push_back(std::string("Source 1")); | 624 publishers.push_back(std::string("Source 1")); |
| 660 publishers.push_back(std::string()); | 625 publishers.push_back(std::string()); |
| 661 publishers.push_back(std::string("Source 3")); | 626 publishers.push_back(std::string("Source 3")); |
| 662 amp_urls.push_back(std::string("http://source1.amp.com")); | 627 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 663 amp_urls.push_back(std::string("http://source2.amp.com")); | 628 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 664 amp_urls.push_back(std::string("http://source3.amp.com")); | 629 amp_urls.push_back(std::string("http://source3.amp.com")); |
| 665 std::string json_str( | 630 std::string json_str( |
| 666 GetTestJsonWithSources(source_urls, publishers, amp_urls)); | 631 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)})); |
| 667 | 632 |
| 668 LoadFromJSONString(json_str); | 633 LoadFromJSONString(json_str); |
| 669 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 634 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 670 { | 635 { |
| 671 const NTPSnippet& snippet = *service()->snippets().front(); | 636 const NTPSnippet& snippet = *service()->snippets().front(); |
| 672 EXPECT_EQ(snippet.sources().size(), 3u); | 637 EXPECT_EQ(snippet.sources().size(), 3u); |
| 673 EXPECT_EQ(snippet.id(), "http://localhost/foobar"); | 638 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 674 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); | 639 EXPECT_EQ(snippet.best_source().url, GURL("http://source1.com")); |
| 675 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); | 640 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 1")); |
| 676 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source1.amp.com")); | 641 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source1.amp.com")); |
| 677 } | 642 } |
| 678 | 643 |
| 679 // Test 2 complete sources, we should choose the first complete source | 644 // Test 2 complete sources, we should choose the first complete source |
| 680 service()->ClearSnippets(); | 645 service()->ClearSnippets(); |
| 681 source_urls.clear(); | 646 source_urls.clear(); |
| 682 source_urls.push_back(std::string("http://source1.com")); | 647 source_urls.push_back(std::string("http://source1.com")); |
| 683 source_urls.push_back(std::string("http://source2.com")); | 648 source_urls.push_back(std::string("http://source2.com")); |
| 684 source_urls.push_back(std::string("http://source3.com")); | 649 source_urls.push_back(std::string("http://source3.com")); |
| 685 publishers.clear(); | 650 publishers.clear(); |
| 686 publishers.push_back(std::string()); | 651 publishers.push_back(std::string()); |
| 687 publishers.push_back(std::string("Source 2")); | 652 publishers.push_back(std::string("Source 2")); |
| 688 publishers.push_back(std::string("Source 3")); | 653 publishers.push_back(std::string("Source 3")); |
| 689 amp_urls.clear(); | 654 amp_urls.clear(); |
| 690 amp_urls.push_back(std::string("http://source1.amp.com")); | 655 amp_urls.push_back(std::string("http://source1.amp.com")); |
| 691 amp_urls.push_back(std::string("http://source2.amp.com")); | 656 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 692 amp_urls.push_back(std::string("http://source3.amp.com")); | 657 amp_urls.push_back(std::string("http://source3.amp.com")); |
| 693 json_str = GetTestJsonWithSources(source_urls, publishers, amp_urls); | 658 json_str = |
| 659 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)}); |
| 694 | 660 |
| 695 LoadFromJSONString(json_str); | 661 LoadFromJSONString(json_str); |
| 696 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 662 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 697 { | 663 { |
| 698 const NTPSnippet& snippet = *service()->snippets().front(); | 664 const NTPSnippet& snippet = *service()->snippets().front(); |
| 699 EXPECT_EQ(snippet.sources().size(), 3u); | 665 EXPECT_EQ(snippet.sources().size(), 3u); |
| 700 EXPECT_EQ(snippet.id(), "http://localhost/foobar"); | 666 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 701 EXPECT_EQ(snippet.best_source().url, GURL("http://source2.com")); | 667 EXPECT_EQ(snippet.best_source().url, GURL("http://source2.com")); |
| 702 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 2")); | 668 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 2")); |
| 703 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source2.amp.com")); | 669 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source2.amp.com")); |
| 704 } | 670 } |
| 705 | 671 |
| 706 // Test 3 complete sources, we should choose the first complete source | 672 // Test 3 complete sources, we should choose the first complete source |
| 707 service()->ClearSnippets(); | 673 service()->ClearSnippets(); |
| 708 source_urls.clear(); | 674 source_urls.clear(); |
| 709 source_urls.push_back(std::string("http://source1.com")); | 675 source_urls.push_back(std::string("http://source1.com")); |
| 710 source_urls.push_back(std::string("http://source2.com")); | 676 source_urls.push_back(std::string("http://source2.com")); |
| 711 source_urls.push_back(std::string("http://source3.com")); | 677 source_urls.push_back(std::string("http://source3.com")); |
| 712 publishers.clear(); | 678 publishers.clear(); |
| 713 publishers.push_back(std::string("Source 1")); | 679 publishers.push_back(std::string("Source 1")); |
| 714 publishers.push_back(std::string("Source 2")); | 680 publishers.push_back(std::string("Source 2")); |
| 715 publishers.push_back(std::string("Source 3")); | 681 publishers.push_back(std::string("Source 3")); |
| 716 amp_urls.clear(); | 682 amp_urls.clear(); |
| 717 amp_urls.push_back(std::string()); | 683 amp_urls.push_back(std::string()); |
| 718 amp_urls.push_back(std::string("http://source2.amp.com")); | 684 amp_urls.push_back(std::string("http://source2.amp.com")); |
| 719 amp_urls.push_back(std::string("http://source3.amp.com")); | 685 amp_urls.push_back(std::string("http://source3.amp.com")); |
| 720 json_str = GetTestJsonWithSources(source_urls, publishers, amp_urls); | 686 json_str = |
| 687 GetTestJson({GetSnippetWithSources(source_urls, publishers, amp_urls)}); |
| 721 | 688 |
| 722 LoadFromJSONString(json_str); | 689 LoadFromJSONString(json_str); |
| 723 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 690 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 724 { | 691 { |
| 725 const NTPSnippet& snippet = *service()->snippets().front(); | 692 const NTPSnippet& snippet = *service()->snippets().front(); |
| 726 EXPECT_EQ(snippet.sources().size(), 3u); | 693 EXPECT_EQ(snippet.sources().size(), 3u); |
| 727 EXPECT_EQ(snippet.id(), "http://localhost/foobar"); | 694 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 728 EXPECT_EQ(snippet.best_source().url, GURL("http://source2.com")); | 695 EXPECT_EQ(snippet.best_source().url, GURL("http://source2.com")); |
| 729 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 2")); | 696 EXPECT_EQ(snippet.best_source().publisher_name, std::string("Source 2")); |
| 730 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source2.amp.com")); | 697 EXPECT_EQ(snippet.best_source().amp_url, GURL("http://source2.amp.com")); |
| 731 } | 698 } |
| 732 } | 699 } |
| 733 | 700 |
| 734 TEST_F(NTPSnippetsServiceTest, LogNumArticlesHistogram) { | 701 TEST_F(NTPSnippetsServiceTest, LogNumArticlesHistogram) { |
| 735 base::HistogramTester tester; | 702 base::HistogramTester tester; |
| 736 LoadFromJSONString(GetInvalidJson()); | 703 LoadFromJSONString(GetTestJson({GetInvalidSnippet()})); |
| 704 |
| 737 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), | 705 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), |
| 738 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); | 706 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); |
| 739 // Invalid JSON shouldn't contribute to NumArticlesFetched. | 707 // Invalid JSON shouldn't contribute to NumArticlesFetched. |
| 740 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), | 708 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), |
| 741 IsEmpty()); | 709 IsEmpty()); |
| 742 // Valid JSON with empty list. | 710 // Valid JSON with empty list. |
| 743 LoadFromJSONString("{ \"recos\": []}"); | 711 LoadFromJSONString(GetTestJson(std::vector<std::string>())); |
| 744 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), | 712 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), |
| 745 ElementsAre(base::Bucket(/*min=*/0, /*count=*/2))); | 713 ElementsAre(base::Bucket(/*min=*/0, /*count=*/2))); |
| 746 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), | 714 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), |
| 747 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); | 715 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); |
| 748 // Snippet list should be populated with size 1. | 716 // Snippet list should be populated with size 1. |
| 749 LoadFromJSONString(GetTestJson()); | 717 LoadFromJSONString(GetTestJson({GetSnippet()})); |
| 750 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), | 718 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), |
| 751 ElementsAre(base::Bucket(/*min=*/0, /*count=*/2), | 719 ElementsAre(base::Bucket(/*min=*/0, /*count=*/2), |
| 752 base::Bucket(/*min=*/1, /*count=*/1))); | 720 base::Bucket(/*min=*/1, /*count=*/1))); |
| 753 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), | 721 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), |
| 754 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), | 722 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), |
| 755 base::Bucket(/*min=*/1, /*count=*/1))); | 723 base::Bucket(/*min=*/1, /*count=*/1))); |
| 756 // Duplicate snippet shouldn't increase the list size. | 724 // Duplicate snippet shouldn't increase the list size. |
| 757 LoadFromJSONString(GetTestJson()); | 725 LoadFromJSONString(GetTestJson({GetSnippet()})); |
| 758 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), | 726 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), |
| 759 ElementsAre(base::Bucket(/*min=*/0, /*count=*/2), | 727 ElementsAre(base::Bucket(/*min=*/0, /*count=*/2), |
| 760 base::Bucket(/*min=*/1, /*count=*/2))); | 728 base::Bucket(/*min=*/1, /*count=*/2))); |
| 761 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), | 729 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), |
| 762 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), | 730 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), |
| 763 base::Bucket(/*min=*/1, /*count=*/2))); | 731 base::Bucket(/*min=*/1, /*count=*/2))); |
| 764 EXPECT_THAT( | 732 EXPECT_THAT( |
| 765 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), | 733 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), |
| 766 IsEmpty()); | 734 IsEmpty()); |
| 767 // Discarding a snippet should decrease the list size. This will only be | 735 // Discarding a snippet should decrease the list size. This will only be |
| 768 // logged after the next fetch. | 736 // logged after the next fetch. |
| 769 EXPECT_TRUE(service()->DiscardSnippet("http://localhost/foobar")); | 737 EXPECT_TRUE(service()->DiscardSnippet(kSnippetUrl)); |
| 770 LoadFromJSONString(GetTestJson()); | 738 LoadFromJSONString(GetTestJson({GetSnippet()})); |
| 771 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), | 739 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), |
| 772 ElementsAre(base::Bucket(/*min=*/0, /*count=*/3), | 740 ElementsAre(base::Bucket(/*min=*/0, /*count=*/3), |
| 773 base::Bucket(/*min=*/1, /*count=*/2))); | 741 base::Bucket(/*min=*/1, /*count=*/2))); |
| 774 // Discarded snippets shouldn't influence NumArticlesFetched. | 742 // Discarded snippets shouldn't influence NumArticlesFetched. |
| 775 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), | 743 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), |
| 776 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), | 744 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), |
| 777 base::Bucket(/*min=*/1, /*count=*/3))); | 745 base::Bucket(/*min=*/1, /*count=*/3))); |
| 778 EXPECT_THAT( | 746 EXPECT_THAT( |
| 779 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), | 747 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), |
| 780 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); | 748 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); |
| 781 // Recreating the service and loading from prefs shouldn't count as fetched | 749 // Recreating the service and loading from prefs shouldn't count as fetched |
| 782 // articles. | 750 // articles. |
| 783 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); | 751 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); |
| 784 CreateSnippetsService(/*enabled=*/true); | 752 CreateSnippetsService(/*enabled=*/true); |
| 785 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4); | 753 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4); |
| 786 } | 754 } |
| 787 | 755 |
| 788 const char kChromeReaderResponseMultipleUrls[] = | 756 TEST_F(NTPSnippetsServiceTest, DiscardShouldRespectAllKnownUrls) { |
| 789 "{ \"recos\": [{ " | 757 const std::string creation = |
| 790 " \"contentInfo\": { " | 758 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()); |
| 791 " \"url\": \"%s\", " | 759 const std::string expiry = |
| 792 " \"creationTimestampSec\": \"%s\", " | 760 NTPSnippet::TimeToJsonString(GetDefaultExpirationTime()); |
| 793 " \"expiryTimestampSec\" : \"%s\"," | 761 const std::vector<std::string> source_urls = { |
| 794 " \"title\": \"Stolen doggie finally gets returned to owner\", " | 762 "http://mashable.com/2016/05/11/stolen", |
| 795 " \"snippet\": \"It\'s at least this man\'s best friend.\", " | 763 "http://www.aol.com/article/2016/05/stolen-doggie", |
| 796 " \"thumbnailUrl\": \"http://t0.gstatic.com/images?q=tbn:1\", " | 764 "http://mashable.com/2016/05/11/stolen?utm_cid=1"}; |
| 797 " \"sourceCorpusInfo\": [{" | 765 const std::vector<std::string> publishers = {"Mashable", "AOL", "Mashable"}; |
| 798 " \"type\" : \"CHROME_LOGS\", " | 766 const std::vector<std::string> amp_urls = { |
| 799 " \"corpusId\": \"http://mashable.com/2016/05/11/stolen\", " | 767 "http://mashable-amphtml.googleusercontent.com/1", |
| 800 " \"publisherData\": { " | 768 "http://t2.gstatic.com/images?q=tbn:3", |
| 801 " \"sourceName\": \"Mashable\", " | 769 "http://t2.gstatic.com/images?q=tbn:3"}; |
| 802 " \"sourceLogoUrl\": \"http://t3.gstatic.com/images?q=tbn:2\" " | |
| 803 " }, " | |
| 804 " \"ampUrl\": \"http://mashable-amphtml.googleusercontent.com/1\" " | |
| 805 " }, { " | |
| 806 " \"type\": \"CHROME_LOGS\", " | |
| 807 " \"corpusId\": \"http://www.aol.com/article/2016/05/stolen-doggie\", " | |
| 808 " \"publisherData\": { " | |
| 809 " \"sourceName\": \"AOL\", " | |
| 810 " \"sourceLogoUrl\": \"http://t2.gstatic.com/images?q=tbn:3\" " | |
| 811 " }, " | |
| 812 " \"ampUrl\": \"http://mashable-amphtml.googleusercontent.com/1\" " | |
| 813 " }, { " | |
| 814 " \"type\": \"CHROME_LOGS\", " | |
| 815 " \"corpusId\": \"http://mashable.com/2016/05/11/stolen?utm_cid=1\", " | |
| 816 " \"publisherData\": { " | |
| 817 " \"sourceName\": \"Mashable\", " | |
| 818 " \"sourceLogoUrl\": \"http://t3.gstatic.com/images?q=tbn:2\" " | |
| 819 " }, " | |
| 820 " \"ampUrl\": \"http://mashable-amphtml.googleusercontent.com/1\" " | |
| 821 " }] " | |
| 822 " }, " | |
| 823 " \"score\" : \"0.099307865\" " | |
| 824 "}]} "; | |
| 825 | 770 |
| 826 TEST_F(NTPSnippetsServiceTest, DiscardShouldRespectAllKnownUrls) { | 771 // Add the snippet from the mashable domain. |
| 827 const std::string url_mashable = "http://mashable.com/2016/05/11/stolen"; | 772 LoadFromJSONString(GetTestJson({GetSnippetWithUrlAndTimesAndSources( |
| 828 const std::string url_aol = | 773 source_urls[0], creation, expiry, source_urls, publishers, amp_urls)})); |
| 829 "http://www.aol.com/article/2016/05/stolen-doggie"; | |
| 830 | |
| 831 LoadFromJSONString(base::StringPrintf( | |
| 832 kChromeReaderResponseMultipleUrls, url_mashable.c_str(), | |
| 833 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | |
| 834 NTPSnippet::TimeToJsonString(base::Time::Now() + | |
| 835 base::TimeDelta::FromHours(1)) | |
| 836 .c_str())); | |
| 837 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 774 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 838 // Discard the snippet via the mashable source corpus ID. | 775 // Discard the snippet via the mashable source corpus ID. |
| 839 EXPECT_TRUE(service()->DiscardSnippet(url_mashable)); | 776 EXPECT_TRUE(service()->DiscardSnippet(source_urls[0])); |
| 840 EXPECT_THAT(service()->snippets(), IsEmpty()); | 777 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 841 | 778 |
| 842 // The same article from the AOL domain should now be detected as discarded. | 779 // The same article from the AOL domain should now be detected as discarded. |
| 843 LoadFromJSONString(base::StringPrintf( | 780 LoadFromJSONString(GetTestJson({GetSnippetWithUrlAndTimesAndSources( |
| 844 kChromeReaderResponseMultipleUrls, url_aol.c_str(), | 781 source_urls[1], creation, expiry, source_urls, publishers, amp_urls)})); |
| 845 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()).c_str(), | |
| 846 NTPSnippet::TimeToJsonString(base::Time::Now() + | |
| 847 base::TimeDelta::FromHours(1)) | |
| 848 .c_str())); | |
| 849 ASSERT_THAT(service()->snippets(), IsEmpty()); | 782 ASSERT_THAT(service()->snippets(), IsEmpty()); |
| 850 } | 783 } |
| 851 | 784 |
| 852 } // namespace ntp_snippets | 785 } // namespace ntp_snippets |
| OLD | NEW |