Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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/doodle/doodle_fetcher_impl.h" | 5 #include "components/doodle/doodle_fetcher_impl.h" |
| 6 | 6 |
| 7 #include <memory> | |
| 7 #include <string> | 8 #include <string> |
| 8 #include <utility> | 9 #include <utility> |
| 9 | 10 |
| 10 #include "base/bind.h" | 11 #include "base/bind.h" |
| 11 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 12 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
| 13 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 14 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "base/test/mock_callback.h" | |
| 15 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 16 #include "base/values.h" | 18 #include "base/values.h" |
| 17 #include "components/google/core/browser/google_switches.h" | 19 #include "components/google/core/browser/google_switches.h" |
| 18 #include "components/google/core/browser/google_url_tracker.h" | 20 #include "components/google/core/browser/google_url_tracker.h" |
| 19 #include "net/http/http_status_code.h" | 21 #include "net/http/http_status_code.h" |
| 20 #include "net/url_request/test_url_fetcher_factory.h" | 22 #include "net/url_request/test_url_fetcher_factory.h" |
| 21 #include "net/url_request/url_request_status.h" | 23 #include "net/url_request/url_request_status.h" |
| 22 #include "net/url_request/url_request_test_util.h" | 24 #include "net/url_request/url_request_test_util.h" |
| 23 #include "testing/gmock/include/gmock/gmock.h" | 25 #include "testing/gmock/include/gmock/gmock.h" |
| 24 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
| 25 | 27 |
| 28 using testing::_; | |
| 29 using testing::DoAll; | |
| 26 using testing::Eq; | 30 using testing::Eq; |
| 31 using testing::SaveArg; | |
| 27 | 32 |
| 28 namespace doodle { | 33 namespace doodle { |
| 29 | 34 |
| 30 namespace { | 35 namespace { |
| 31 | 36 |
| 32 const char kDoodleConfigPath[] = "/async/ddljson"; | 37 const char kDoodleConfigPath[] = "/async/ddljson"; |
| 33 | 38 |
| 34 // Required to instantiate a GoogleUrlTracker in UNIT_TEST_MODE. | 39 // Required to instantiate a GoogleUrlTracker in UNIT_TEST_MODE. |
| 35 class GoogleURLTrackerClientStub : public GoogleURLTrackerClient { | 40 class GoogleURLTrackerClientStub : public GoogleURLTrackerClient { |
| 36 public: | 41 public: |
| 37 GoogleURLTrackerClientStub() {} | 42 GoogleURLTrackerClientStub() {} |
| 38 ~GoogleURLTrackerClientStub() override {} | 43 ~GoogleURLTrackerClientStub() override {} |
| 39 | 44 |
| 40 bool IsBackgroundNetworkingEnabled() override { return true; } | 45 bool IsBackgroundNetworkingEnabled() override { return true; } |
| 41 | 46 |
| 42 PrefService* GetPrefs() override { return nullptr; } | 47 PrefService* GetPrefs() override { return nullptr; } |
| 43 | 48 |
| 44 net::URLRequestContextGetter* GetRequestContext() override { return nullptr; } | 49 net::URLRequestContextGetter* GetRequestContext() override { return nullptr; } |
| 45 | 50 |
| 46 private: | 51 private: |
| 47 DISALLOW_COPY_AND_ASSIGN(GoogleURLTrackerClientStub); | 52 DISALLOW_COPY_AND_ASSIGN(GoogleURLTrackerClientStub); |
| 48 }; | 53 }; |
| 49 | 54 |
| 50 std::string Resolve(const std::string& relative_url) { | 55 GURL Resolve(const std::string& relative_url) { |
|
Marc Treib
2017/03/22 13:44:07
Should this be a member of the test class and use
fhorschig
2017/03/22 14:27:41
Sounds reasonable.
Marc Treib
2017/03/22 15:35:37
Done.
| |
| 51 return GURL(GoogleURLTracker::kDefaultGoogleHomepage) | 56 return GURL(GoogleURLTracker::kDefaultGoogleHomepage).Resolve(relative_url); |
| 52 .Resolve(relative_url) | |
| 53 .spec(); | |
| 54 } | 57 } |
| 55 | 58 |
| 56 void ParseJson( | 59 void ParseJson( |
| 57 const std::string& json, | 60 const std::string& json, |
| 58 const base::Callback<void(std::unique_ptr<base::Value> json)>& success, | 61 const base::Callback<void(std::unique_ptr<base::Value> json)>& success, |
| 59 const base::Callback<void(const std::string&)>& error) { | 62 const base::Callback<void(const std::string&)>& error) { |
| 60 base::JSONReader json_reader; | 63 base::JSONReader json_reader; |
| 61 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json); | 64 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json); |
| 62 if (value) { | 65 if (value) { |
| 63 success.Run(std::move(value)); | 66 success.Run(std::move(value)); |
| 64 } else { | 67 } else { |
| 65 error.Run(json_reader.GetErrorMessage()); | 68 error.Run(json_reader.GetErrorMessage()); |
| 66 } | 69 } |
| 67 } | 70 } |
| 68 | 71 |
| 69 } // namespace | 72 } // namespace |
| 70 | 73 |
| 71 class DoodleFetcherImplTest : public testing::Test { | 74 class DoodleFetcherImplTest : public testing::Test { |
| 72 public: | 75 public: |
| 73 DoodleFetcherImplTest() | 76 DoodleFetcherImplTest() |
| 74 : url_(GURL(GoogleURLTracker::kDefaultGoogleHomepage)), | 77 : google_url_tracker_(base::MakeUnique<GoogleURLTrackerClientStub>(), |
| 75 google_url_tracker_(base::MakeUnique<GoogleURLTrackerClientStub>(), | |
| 76 GoogleURLTracker::UNIT_TEST_MODE), | 78 GoogleURLTracker::UNIT_TEST_MODE), |
| 77 doodle_fetcher_( | 79 doodle_fetcher_( |
| 78 new net::TestURLRequestContextGetter(message_loop_.task_runner()), | 80 new net::TestURLRequestContextGetter(message_loop_.task_runner()), |
| 79 &google_url_tracker_, | 81 &google_url_tracker_, |
| 80 base::Bind(ParseJson)) {} | 82 base::Bind(ParseJson)) {} |
| 81 | 83 |
| 82 void RespondWithData(const std::string& data) { | 84 void RespondWithData(const std::string& data) { |
| 83 RespondToFetcherWithData(GetRunningFetcher(), data); | 85 net::TestURLFetcher* url_fetcher = GetRunningFetcher(); |
| 84 } | |
| 85 | |
| 86 void RespondToFetcherWithData(net::TestURLFetcher* url_fetcher, | |
| 87 const std::string& data) { | |
| 88 url_fetcher->set_status(net::URLRequestStatus()); | 86 url_fetcher->set_status(net::URLRequestStatus()); |
| 89 url_fetcher->set_response_code(net::HTTP_OK); | 87 url_fetcher->set_response_code(net::HTTP_OK); |
| 90 url_fetcher->SetResponseString(data); | 88 url_fetcher->SetResponseString(data); |
| 91 // Call the URLFetcher delegate to continue the test. | 89 // Call the URLFetcher delegate to continue the test. |
| 92 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); | 90 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); |
| 93 } | 91 } |
| 94 | 92 |
| 95 void RespondWithError(int error_code) { | 93 void RespondWithError(int error_code) { |
| 96 net::TestURLFetcher* url_fetcher = GetRunningFetcher(); | 94 net::TestURLFetcher* url_fetcher = GetRunningFetcher(); |
| 97 url_fetcher->set_status(net::URLRequestStatus::FromError(error_code)); | 95 url_fetcher->set_status(net::URLRequestStatus::FromError(error_code)); |
| 98 url_fetcher->SetResponseString(""); | 96 url_fetcher->SetResponseString(""); |
| 99 // Call the URLFetcher delegate to continue the test. | 97 // Call the URLFetcher delegate to continue the test. |
| 100 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); | 98 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); |
| 101 } | 99 } |
| 102 | 100 |
| 103 net::TestURLFetcher* GetRunningFetcher() { | 101 net::TestURLFetcher* GetRunningFetcher() { |
| 104 // All created TestURLFetchers have ID 0 by default. | 102 // All created TestURLFetchers have ID 0 by default. |
| 105 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); | 103 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); |
| 106 DCHECK(url_fetcher); | 104 DCHECK(url_fetcher); |
| 107 return url_fetcher; | 105 return url_fetcher; |
| 108 } | 106 } |
| 109 | 107 |
| 110 // TODO(treib): Replace with a MockCallback plus testing::SaveArgs? | 108 // TODO(treib): Replace with a MockCallback plus testing::SaveArgs? |
|
Marc Treib
2017/03/22 13:44:07
I'm not quite sure about this one. I've converted
fhorschig
2017/03/22 14:27:41
Less magic is relative but it's certainly easier t
Marc Treib
2017/03/22 15:35:37
Done.
| |
| 111 DoodleFetcherImpl::FinishedCallback CreateResponseSavingCallback( | 109 DoodleFetcherImpl::FinishedCallback CreateResponseSavingCallback( |
| 112 DoodleState* state_out, | 110 DoodleState* state_out, |
| 113 base::TimeDelta* time_to_live_out, | 111 base::TimeDelta* time_to_live_out, |
| 114 base::Optional<DoodleConfig>* config_out) { | 112 base::Optional<DoodleConfig>* config_out) { |
| 115 return base::BindOnce( | 113 return base::BindOnce( |
| 116 [](DoodleState* state_out, base::TimeDelta* time_to_live_out, | 114 [](DoodleState* state_out, base::TimeDelta* time_to_live_out, |
| 117 base::Optional<DoodleConfig>* config_out, DoodleState state, | 115 base::Optional<DoodleConfig>* config_out, DoodleState state, |
| 118 base::TimeDelta time_to_live, | 116 base::TimeDelta time_to_live, |
| 119 const base::Optional<DoodleConfig>& config) { | 117 const base::Optional<DoodleConfig>& config) { |
| 120 if (state_out) { | 118 if (state_out) { |
| 121 *state_out = state; | 119 *state_out = state; |
| 122 } | 120 } |
| 123 if (time_to_live_out) { | 121 if (time_to_live_out) { |
| 124 *time_to_live_out = time_to_live; | 122 *time_to_live_out = time_to_live; |
| 125 } | 123 } |
| 126 if (config_out) { | 124 if (config_out) { |
| 127 *config_out = config; | 125 *config_out = config; |
| 128 } | 126 } |
| 129 }, | 127 }, |
| 130 state_out, time_to_live_out, config_out); | 128 state_out, time_to_live_out, config_out); |
| 131 } | 129 } |
| 132 | 130 |
| 133 DoodleFetcherImpl* doodle_fetcher() { return &doodle_fetcher_; } | 131 DoodleFetcherImpl* doodle_fetcher() { return &doodle_fetcher_; } |
| 134 | 132 |
| 135 GURL GetGoogleBaseURL() { return google_url_tracker_.google_url(); } | 133 GURL GetGoogleBaseURL() { return google_url_tracker_.google_url(); } |
| 136 | 134 |
| 137 private: | 135 private: |
| 138 base::MessageLoop message_loop_; | 136 base::MessageLoop message_loop_; |
| 139 GURL url_; | |
| 140 net::TestURLFetcherFactory url_fetcher_factory_; | 137 net::TestURLFetcherFactory url_fetcher_factory_; |
| 141 GoogleURLTracker google_url_tracker_; | 138 GoogleURLTracker google_url_tracker_; |
| 142 DoodleFetcherImpl doodle_fetcher_; | 139 DoodleFetcherImpl doodle_fetcher_; |
| 143 }; | 140 }; |
| 144 | 141 |
| 145 TEST_F(DoodleFetcherImplTest, ReturnsFromFetchWithoutError) { | 142 TEST_F(DoodleFetcherImplTest, ReturnsFromFetchWithoutError) { |
| 143 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; | |
| 144 doodle_fetcher()->FetchDoodle(callback.Get()); | |
| 145 | |
| 146 DoodleState state(DoodleState::NO_DOODLE); | 146 DoodleState state(DoodleState::NO_DOODLE); |
| 147 base::Optional<DoodleConfig> response; | 147 base::Optional<DoodleConfig> response; |
| 148 | 148 EXPECT_CALL(callback, Run(_, _, _)) |
|
fhorschig
2017/03/22 14:27:41
It's somewhat confusing to see the expectation aft
Marc Treib
2017/03/22 15:35:37
I read this as: I expect the call when I send the
fhorschig
2017/03/22 17:00:56
No, don't move it up. It also makes sense that the
| |
| 149 doodle_fetcher()->FetchDoodle( | 149 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<2>(&response))); |
| 150 CreateResponseSavingCallback(&state, nullptr, &response)); | |
| 151 RespondWithData(R"json({"ddljson": { | 150 RespondWithData(R"json({"ddljson": { |
| 152 "time_to_live_ms":55000, | 151 "time_to_live_ms":55000, |
| 153 "large_image": {"url":"/logos/doodles/2015/some.gif"} | 152 "large_image": {"url":"/logos/doodles/2015/some.gif"} |
| 154 }})json"); | 153 }})json"); |
| 155 | 154 |
| 156 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); | 155 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); |
| 157 EXPECT_TRUE(response.has_value()); | 156 EXPECT_TRUE(response.has_value()); |
| 158 } | 157 } |
| 159 | 158 |
| 160 TEST_F(DoodleFetcherImplTest, ReturnsFrom404FetchWithError) { | 159 TEST_F(DoodleFetcherImplTest, ReturnsFrom404FetchWithError) { |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 344 "url":"/logos/doodles/2015/new-years-eve-2015-59854387958251-thp.png", | 343 "url":"/logos/doodles/2015/new-years-eve-2015-59854387958251-thp.png", |
| 345 "width":510 | 344 "width":510 |
| 346 } | 345 } |
| 347 }})json"); | 346 }})json"); |
| 348 | 347 |
| 349 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); | 348 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); |
| 350 ASSERT_TRUE(response.has_value()); | 349 ASSERT_TRUE(response.has_value()); |
| 351 DoodleConfig config = response.value(); | 350 DoodleConfig config = response.value(); |
| 352 | 351 |
| 353 EXPECT_TRUE(config.large_image.url.is_valid()); | 352 EXPECT_TRUE(config.large_image.url.is_valid()); |
| 354 EXPECT_THAT(config.large_image.url.spec(), | 353 EXPECT_THAT(config.large_image.url, |
| 355 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" | 354 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" |
| 356 "8251-hp.gif"))); | 355 "8251-hp.gif"))); |
| 357 EXPECT_THAT(config.large_image.width, Eq(489)); | 356 EXPECT_THAT(config.large_image.width, Eq(489)); |
| 358 EXPECT_THAT(config.large_image.height, Eq(225)); | 357 EXPECT_THAT(config.large_image.height, Eq(225)); |
| 359 EXPECT_TRUE(config.large_image.is_animated_gif); | 358 EXPECT_TRUE(config.large_image.is_animated_gif); |
| 360 EXPECT_FALSE(config.large_image.is_cta); | 359 EXPECT_FALSE(config.large_image.is_cta); |
| 361 | 360 |
| 362 ASSERT_TRUE(config.transparent_large_image.has_value()); | 361 ASSERT_TRUE(config.transparent_large_image.has_value()); |
| 363 EXPECT_TRUE(config.transparent_large_image->url.is_valid()); | 362 EXPECT_TRUE(config.transparent_large_image->url.is_valid()); |
| 364 EXPECT_THAT(config.transparent_large_image->url.spec(), | 363 EXPECT_THAT(config.transparent_large_image->url, |
| 365 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" | 364 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" |
| 366 "8251-thp.png"))); | 365 "8251-thp.png"))); |
| 367 EXPECT_THAT(config.transparent_large_image->width, Eq(510)); | 366 EXPECT_THAT(config.transparent_large_image->width, Eq(510)); |
| 368 EXPECT_THAT(config.transparent_large_image->height, Eq(225)); | 367 EXPECT_THAT(config.transparent_large_image->height, Eq(225)); |
| 369 EXPECT_FALSE(config.transparent_large_image->is_animated_gif); | 368 EXPECT_FALSE(config.transparent_large_image->is_animated_gif); |
| 370 EXPECT_FALSE(config.transparent_large_image->is_cta); | 369 EXPECT_FALSE(config.transparent_large_image->is_cta); |
| 371 | 370 |
| 372 ASSERT_TRUE(config.large_cta_image.has_value()); | 371 ASSERT_TRUE(config.large_cta_image.has_value()); |
| 373 EXPECT_TRUE(config.large_cta_image->url.is_valid()); | 372 EXPECT_TRUE(config.large_cta_image->url.is_valid()); |
| 374 EXPECT_THAT(config.large_cta_image->url.spec(), | 373 EXPECT_THAT(config.large_cta_image->url, |
| 375 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" | 374 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" |
| 376 "8251-cta.gif"))); | 375 "8251-cta.gif"))); |
| 377 EXPECT_THAT(config.large_cta_image->width, Eq(489)); | 376 EXPECT_THAT(config.large_cta_image->width, Eq(489)); |
| 378 EXPECT_THAT(config.large_cta_image->height, Eq(225)); | 377 EXPECT_THAT(config.large_cta_image->height, Eq(225)); |
| 379 EXPECT_TRUE(config.large_cta_image->is_animated_gif); | 378 EXPECT_TRUE(config.large_cta_image->is_animated_gif); |
| 380 EXPECT_TRUE(config.large_cta_image->is_cta); | 379 EXPECT_TRUE(config.large_cta_image->is_cta); |
| 381 } | 380 } |
| 382 | 381 |
| 383 TEST_F(DoodleFetcherImplTest, RespondsToMultipleRequestsWithSameFetcher) { | 382 TEST_F(DoodleFetcherImplTest, RespondsToMultipleRequestsWithSameFetcher) { |
| 384 DoodleState state1(DoodleState::NO_DOODLE); | 383 DoodleState state1(DoodleState::NO_DOODLE); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 407 EXPECT_TRUE(response1.has_value()); | 406 EXPECT_TRUE(response1.has_value()); |
| 408 EXPECT_THAT(state2, Eq(DoodleState::AVAILABLE)); | 407 EXPECT_THAT(state2, Eq(DoodleState::AVAILABLE)); |
| 409 EXPECT_TRUE(response2.has_value()); | 408 EXPECT_TRUE(response2.has_value()); |
| 410 } | 409 } |
| 411 | 410 |
| 412 TEST_F(DoodleFetcherImplTest, ReceivesBaseUrlFromTracker) { | 411 TEST_F(DoodleFetcherImplTest, ReceivesBaseUrlFromTracker) { |
| 413 doodle_fetcher()->FetchDoodle(CreateResponseSavingCallback( | 412 doodle_fetcher()->FetchDoodle(CreateResponseSavingCallback( |
| 414 /*state=*/nullptr, nullptr, /*response=*/nullptr)); | 413 /*state=*/nullptr, nullptr, /*response=*/nullptr)); |
| 415 | 414 |
| 416 EXPECT_THAT(GetRunningFetcher()->GetOriginalURL(), | 415 EXPECT_THAT(GetRunningFetcher()->GetOriginalURL(), |
| 417 Eq(GetGoogleBaseURL().Resolve(kDoodleConfigPath))); | 416 Eq(GetGoogleBaseURL().Resolve(kDoodleConfigPath))); |
|
Marc Treib
2017/03/22 13:44:07
This doesn't really test anything, does it? The Go
fhorschig
2017/03/22 14:27:41
Yes. Meanwhile, this case is covered by pretty muc
Marc Treib
2017/03/22 15:35:37
GoogleBaseURLTracker doesn't seem to have an easy
fhorschig
2017/03/22 17:00:56
sgtm (I can remotely remember to have stumbled upo
| |
| 418 } | 417 } |
| 419 | 418 |
| 420 TEST_F(DoodleFetcherImplTest, OverridesBaseUrlWithCommandLineArgument) { | 419 TEST_F(DoodleFetcherImplTest, OverridesBaseUrlWithCommandLineArgument) { |
| 421 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( | 420 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
| 422 switches::kGoogleBaseURL, "http://www.google.kz"); | 421 switches::kGoogleBaseURL, "http://www.google.kz"); |
| 423 | 422 |
| 424 doodle_fetcher()->FetchDoodle(CreateResponseSavingCallback( | 423 doodle_fetcher()->FetchDoodle(CreateResponseSavingCallback( |
| 425 /*state=*/nullptr, nullptr, /*response=*/nullptr)); | 424 /*state=*/nullptr, nullptr, /*response=*/nullptr)); |
| 426 | 425 |
| 427 EXPECT_THAT(GetRunningFetcher()->GetOriginalURL(), | 426 EXPECT_THAT(GetRunningFetcher()->GetOriginalURL(), |
| 428 Eq(GURL("http://www.google.kz").Resolve(kDoodleConfigPath))); | 427 Eq(GURL("http://www.google.kz").Resolve(kDoodleConfigPath))); |
| 429 } | 428 } |
| 430 | 429 |
| 431 } // namespace doodle | 430 } // namespace doodle |
| OLD | NEW |