| 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) { | |
| 51 return GURL(GoogleURLTracker::kDefaultGoogleHomepage) | |
| 52 .Resolve(relative_url) | |
| 53 .spec(); | |
| 54 } | |
| 55 | |
| 56 void ParseJson( | 55 void ParseJson( |
| 57 const std::string& json, | 56 const std::string& json, |
| 58 const base::Callback<void(std::unique_ptr<base::Value> json)>& success, | 57 const base::Callback<void(std::unique_ptr<base::Value> json)>& success, |
| 59 const base::Callback<void(const std::string&)>& error) { | 58 const base::Callback<void(const std::string&)>& error) { |
| 60 base::JSONReader json_reader; | 59 base::JSONReader json_reader; |
| 61 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json); | 60 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json); |
| 62 if (value) { | 61 if (value) { |
| 63 success.Run(std::move(value)); | 62 success.Run(std::move(value)); |
| 64 } else { | 63 } else { |
| 65 error.Run(json_reader.GetErrorMessage()); | 64 error.Run(json_reader.GetErrorMessage()); |
| 66 } | 65 } |
| 67 } | 66 } |
| 68 | 67 |
| 69 } // namespace | 68 } // namespace |
| 70 | 69 |
| 71 class DoodleFetcherImplTest : public testing::Test { | 70 class DoodleFetcherImplTest : public testing::Test { |
| 72 public: | 71 public: |
| 73 DoodleFetcherImplTest() | 72 DoodleFetcherImplTest() |
| 74 : url_(GURL(GoogleURLTracker::kDefaultGoogleHomepage)), | 73 : google_url_tracker_(base::MakeUnique<GoogleURLTrackerClientStub>(), |
| 75 google_url_tracker_(base::MakeUnique<GoogleURLTrackerClientStub>(), | |
| 76 GoogleURLTracker::UNIT_TEST_MODE), | 74 GoogleURLTracker::UNIT_TEST_MODE), |
| 77 doodle_fetcher_( | 75 doodle_fetcher_( |
| 78 new net::TestURLRequestContextGetter(message_loop_.task_runner()), | 76 new net::TestURLRequestContextGetter(message_loop_.task_runner()), |
| 79 &google_url_tracker_, | 77 &google_url_tracker_, |
| 80 base::Bind(ParseJson)) {} | 78 base::Bind(ParseJson)) {} |
| 81 | 79 |
| 82 void RespondWithData(const std::string& data) { | 80 void RespondWithData(const std::string& data) { |
| 83 RespondToFetcherWithData(GetRunningFetcher(), data); | 81 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()); | 82 url_fetcher->set_status(net::URLRequestStatus()); |
| 89 url_fetcher->set_response_code(net::HTTP_OK); | 83 url_fetcher->set_response_code(net::HTTP_OK); |
| 90 url_fetcher->SetResponseString(data); | 84 url_fetcher->SetResponseString(data); |
| 91 // Call the URLFetcher delegate to continue the test. | 85 // Call the URLFetcher delegate to continue the test. |
| 92 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); | 86 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); |
| 93 } | 87 } |
| 94 | 88 |
| 95 void RespondWithError(int error_code) { | 89 void RespondWithError(int error_code) { |
| 96 net::TestURLFetcher* url_fetcher = GetRunningFetcher(); | 90 net::TestURLFetcher* url_fetcher = GetRunningFetcher(); |
| 97 url_fetcher->set_status(net::URLRequestStatus::FromError(error_code)); | 91 url_fetcher->set_status(net::URLRequestStatus::FromError(error_code)); |
| 98 url_fetcher->SetResponseString(""); | 92 url_fetcher->SetResponseString(""); |
| 99 // Call the URLFetcher delegate to continue the test. | 93 // Call the URLFetcher delegate to continue the test. |
| 100 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); | 94 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); |
| 101 } | 95 } |
| 102 | 96 |
| 103 net::TestURLFetcher* GetRunningFetcher() { | 97 net::TestURLFetcher* GetRunningFetcher() { |
| 104 // All created TestURLFetchers have ID 0 by default. | 98 // All created TestURLFetchers have ID 0 by default. |
| 105 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); | 99 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0); |
| 106 DCHECK(url_fetcher); | 100 DCHECK(url_fetcher); |
| 107 return url_fetcher; | 101 return url_fetcher; |
| 108 } | 102 } |
| 109 | 103 |
| 110 // TODO(treib): Replace with a MockCallback plus testing::SaveArgs? | |
| 111 DoodleFetcherImpl::FinishedCallback CreateResponseSavingCallback( | |
| 112 DoodleState* state_out, | |
| 113 base::TimeDelta* time_to_live_out, | |
| 114 base::Optional<DoodleConfig>* config_out) { | |
| 115 return base::BindOnce( | |
| 116 [](DoodleState* state_out, base::TimeDelta* time_to_live_out, | |
| 117 base::Optional<DoodleConfig>* config_out, DoodleState state, | |
| 118 base::TimeDelta time_to_live, | |
| 119 const base::Optional<DoodleConfig>& config) { | |
| 120 if (state_out) { | |
| 121 *state_out = state; | |
| 122 } | |
| 123 if (time_to_live_out) { | |
| 124 *time_to_live_out = time_to_live; | |
| 125 } | |
| 126 if (config_out) { | |
| 127 *config_out = config; | |
| 128 } | |
| 129 }, | |
| 130 state_out, time_to_live_out, config_out); | |
| 131 } | |
| 132 | |
| 133 DoodleFetcherImpl* doodle_fetcher() { return &doodle_fetcher_; } | 104 DoodleFetcherImpl* doodle_fetcher() { return &doodle_fetcher_; } |
| 134 | 105 |
| 135 GURL GetGoogleBaseURL() { return google_url_tracker_.google_url(); } | 106 GURL GetGoogleBaseURL() { return google_url_tracker_.google_url(); } |
| 136 | 107 |
| 108 GURL Resolve(const std::string& relative_url) { |
| 109 return GetGoogleBaseURL().Resolve(relative_url); |
| 110 } |
| 111 |
| 137 private: | 112 private: |
| 138 base::MessageLoop message_loop_; | 113 base::MessageLoop message_loop_; |
| 139 GURL url_; | |
| 140 net::TestURLFetcherFactory url_fetcher_factory_; | 114 net::TestURLFetcherFactory url_fetcher_factory_; |
| 141 GoogleURLTracker google_url_tracker_; | 115 GoogleURLTracker google_url_tracker_; |
| 142 DoodleFetcherImpl doodle_fetcher_; | 116 DoodleFetcherImpl doodle_fetcher_; |
| 143 }; | 117 }; |
| 144 | 118 |
| 145 TEST_F(DoodleFetcherImplTest, ReturnsFromFetchWithoutError) { | 119 TEST_F(DoodleFetcherImplTest, ReturnsFromFetchWithoutError) { |
| 146 DoodleState state(DoodleState::NO_DOODLE); | 120 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 121 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 122 |
| 123 DoodleState state = DoodleState::NO_DOODLE; |
| 147 base::Optional<DoodleConfig> response; | 124 base::Optional<DoodleConfig> response; |
| 148 | 125 EXPECT_CALL(callback, Run(_, _, _)) |
| 149 doodle_fetcher()->FetchDoodle( | 126 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<2>(&response))); |
| 150 CreateResponseSavingCallback(&state, nullptr, &response)); | |
| 151 RespondWithData(R"json({"ddljson": { | 127 RespondWithData(R"json({"ddljson": { |
| 152 "time_to_live_ms":55000, | 128 "time_to_live_ms":55000, |
| 153 "large_image": {"url":"/logos/doodles/2015/some.gif"} | 129 "large_image": {"url":"/logos/doodles/2015/some.gif"} |
| 154 }})json"); | 130 }})json"); |
| 155 | 131 |
| 156 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); | 132 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); |
| 157 EXPECT_TRUE(response.has_value()); | 133 EXPECT_TRUE(response.has_value()); |
| 158 } | 134 } |
| 159 | 135 |
| 160 TEST_F(DoodleFetcherImplTest, ReturnsFrom404FetchWithError) { | 136 TEST_F(DoodleFetcherImplTest, ReturnsFrom404FetchWithError) { |
| 161 DoodleState state(DoodleState::NO_DOODLE); | 137 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 138 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 139 |
| 140 DoodleState state = DoodleState::NO_DOODLE; |
| 162 base::Optional<DoodleConfig> response; | 141 base::Optional<DoodleConfig> response; |
| 163 | 142 EXPECT_CALL(callback, Run(_, _, _)) |
| 164 doodle_fetcher()->FetchDoodle( | 143 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<2>(&response))); |
| 165 CreateResponseSavingCallback(&state, nullptr, &response)); | |
| 166 RespondWithError(net::ERR_FILE_NOT_FOUND); | 144 RespondWithError(net::ERR_FILE_NOT_FOUND); |
| 167 | 145 |
| 168 EXPECT_THAT(state, Eq(DoodleState::DOWNLOAD_ERROR)); | 146 EXPECT_THAT(state, Eq(DoodleState::DOWNLOAD_ERROR)); |
| 169 EXPECT_FALSE(response.has_value()); | 147 EXPECT_FALSE(response.has_value()); |
| 170 } | 148 } |
| 171 | 149 |
| 172 TEST_F(DoodleFetcherImplTest, ReturnsErrorForInvalidJson) { | 150 TEST_F(DoodleFetcherImplTest, ReturnsErrorForInvalidJson) { |
| 173 DoodleState state(DoodleState::NO_DOODLE); | 151 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 152 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 153 |
| 154 DoodleState state = DoodleState::NO_DOODLE; |
| 174 base::Optional<DoodleConfig> response; | 155 base::Optional<DoodleConfig> response; |
| 175 | 156 EXPECT_CALL(callback, Run(_, _, _)) |
| 176 doodle_fetcher()->FetchDoodle( | 157 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<2>(&response))); |
| 177 CreateResponseSavingCallback(&state, nullptr, &response)); | |
| 178 RespondWithData("}"); | 158 RespondWithData("}"); |
| 179 | 159 |
| 180 EXPECT_THAT(state, Eq(DoodleState::PARSING_ERROR)); | 160 EXPECT_THAT(state, Eq(DoodleState::PARSING_ERROR)); |
| 181 EXPECT_FALSE(response.has_value()); | 161 EXPECT_FALSE(response.has_value()); |
| 182 } | 162 } |
| 183 | 163 |
| 184 TEST_F(DoodleFetcherImplTest, ReturnsErrorForIncompleteJson) { | 164 TEST_F(DoodleFetcherImplTest, ReturnsErrorForIncompleteJson) { |
| 185 DoodleState state(DoodleState::NO_DOODLE); | 165 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 166 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 167 |
| 168 DoodleState state = DoodleState::NO_DOODLE; |
| 186 base::Optional<DoodleConfig> response; | 169 base::Optional<DoodleConfig> response; |
| 187 | 170 EXPECT_CALL(callback, Run(_, _, _)) |
| 188 doodle_fetcher()->FetchDoodle( | 171 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<2>(&response))); |
| 189 CreateResponseSavingCallback(&state, nullptr, &response)); | |
| 190 RespondWithData("{}"); | 172 RespondWithData("{}"); |
| 191 | 173 |
| 192 EXPECT_THAT(state, Eq(DoodleState::PARSING_ERROR)); | 174 EXPECT_THAT(state, Eq(DoodleState::PARSING_ERROR)); |
| 193 EXPECT_FALSE(response.has_value()); | 175 EXPECT_FALSE(response.has_value()); |
| 194 } | 176 } |
| 195 | 177 |
| 196 TEST_F(DoodleFetcherImplTest, ResponseContainsValidBaseInformation) { | 178 TEST_F(DoodleFetcherImplTest, ResponseContainsValidBaseInformation) { |
| 197 DoodleState state(DoodleState::NO_DOODLE); | 179 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 180 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 181 |
| 182 DoodleState state = DoodleState::NO_DOODLE; |
| 198 base::TimeDelta time_to_live; | 183 base::TimeDelta time_to_live; |
| 199 base::Optional<DoodleConfig> response; | 184 base::Optional<DoodleConfig> response; |
| 200 | 185 EXPECT_CALL(callback, Run(_, _, _)) |
| 201 doodle_fetcher()->FetchDoodle( | 186 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<1>(&time_to_live), |
| 202 CreateResponseSavingCallback(&state, &time_to_live, &response)); | 187 SaveArg<2>(&response))); |
| 203 RespondWithData(R"json()]}'{ | 188 RespondWithData(R"json()]}'{ |
| 204 "ddljson": { | 189 "ddljson": { |
| 205 "alt_text":"Mouseover Text", | 190 "alt_text":"Mouseover Text", |
| 206 "doodle_type":"SIMPLE", | 191 "doodle_type":"SIMPLE", |
| 207 "interactive_html":"\u003cstyle\u003e\u003c\/style\u003e", | 192 "interactive_html":"\u003cstyle\u003e\u003c\/style\u003e", |
| 208 "search_url":"/search?q\u003dtest", | 193 "search_url":"/search?q\u003dtest", |
| 209 "target_url":"/search?q\u003dtest\u0026sa\u003dX\u0026ved\u003d0ahUKEw", | 194 "target_url":"/search?q\u003dtest\u0026sa\u003dX\u0026ved\u003d0ahUKEw", |
| 210 "time_to_live_ms":55000, | 195 "time_to_live_ms":55000, |
| 211 "large_image": { | 196 "large_image": { |
| 212 "url":"/logos/doodles/2015/new-years-eve-2015-59854387958251-hp.gif" | 197 "url":"/logos/doodles/2015/new-years-eve-2015-59854387958251-hp.gif" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 229 EXPECT_THAT(config.interactive_html, | 214 EXPECT_THAT(config.interactive_html, |
| 230 Eq("\u003cstyle\u003e\u003c/style\u003e")); | 215 Eq("\u003cstyle\u003e\u003c/style\u003e")); |
| 231 | 216 |
| 232 EXPECT_FALSE(config.large_cta_image.has_value()); | 217 EXPECT_FALSE(config.large_cta_image.has_value()); |
| 233 EXPECT_FALSE(config.transparent_large_image.has_value()); | 218 EXPECT_FALSE(config.transparent_large_image.has_value()); |
| 234 | 219 |
| 235 EXPECT_THAT(time_to_live, Eq(base::TimeDelta::FromMilliseconds(55000))); | 220 EXPECT_THAT(time_to_live, Eq(base::TimeDelta::FromMilliseconds(55000))); |
| 236 } | 221 } |
| 237 | 222 |
| 238 TEST_F(DoodleFetcherImplTest, DoodleExpiresWithinThirtyDaysForTooLargeTTL) { | 223 TEST_F(DoodleFetcherImplTest, DoodleExpiresWithinThirtyDaysForTooLargeTTL) { |
| 239 DoodleState state(DoodleState::NO_DOODLE); | 224 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 225 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 226 |
| 227 DoodleState state = DoodleState::NO_DOODLE; |
| 240 base::TimeDelta time_to_live; | 228 base::TimeDelta time_to_live; |
| 241 base::Optional<DoodleConfig> response; | 229 base::Optional<DoodleConfig> response; |
| 242 | 230 EXPECT_CALL(callback, Run(_, _, _)) |
| 243 doodle_fetcher()->FetchDoodle( | 231 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<1>(&time_to_live), |
| 244 CreateResponseSavingCallback(&state, &time_to_live, &response)); | 232 SaveArg<2>(&response))); |
| 245 RespondWithData(R"json({"ddljson": { | 233 RespondWithData(R"json({"ddljson": { |
| 246 "time_to_live_ms":5184000000, | 234 "time_to_live_ms":5184000000, |
| 247 "large_image": {"url":"/logos/doodles/2015/some.gif"} | 235 "large_image": {"url":"/logos/doodles/2015/some.gif"} |
| 248 }})json"); // 60 days | 236 }})json"); // 60 days |
| 249 | 237 |
| 250 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); | 238 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); |
| 251 EXPECT_TRUE(response.has_value()); | 239 EXPECT_TRUE(response.has_value()); |
| 252 EXPECT_THAT(time_to_live, | 240 EXPECT_THAT(time_to_live, |
| 253 Eq(base::TimeDelta::FromMilliseconds(30ul * 24 * 60 * 60 * | 241 Eq(base::TimeDelta::FromMilliseconds(30ul * 24 * 60 * 60 * |
| 254 1000))); // 30 days | 242 1000))); // 30 days |
| 255 } | 243 } |
| 256 | 244 |
| 257 TEST_F(DoodleFetcherImplTest, DoodleExpiresImmediatelyWithNegativeTTL) { | 245 TEST_F(DoodleFetcherImplTest, DoodleExpiresImmediatelyWithNegativeTTL) { |
| 258 DoodleState state(DoodleState::NO_DOODLE); | 246 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 247 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 248 |
| 249 DoodleState state = DoodleState::NO_DOODLE; |
| 259 base::TimeDelta time_to_live; | 250 base::TimeDelta time_to_live; |
| 260 base::Optional<DoodleConfig> response; | 251 base::Optional<DoodleConfig> response; |
| 261 | 252 EXPECT_CALL(callback, Run(_, _, _)) |
| 262 doodle_fetcher()->FetchDoodle( | 253 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<1>(&time_to_live), |
| 263 CreateResponseSavingCallback(&state, &time_to_live, &response)); | 254 SaveArg<2>(&response))); |
| 264 RespondWithData(R"json({"ddljson": { | 255 RespondWithData(R"json({"ddljson": { |
| 265 "time_to_live_ms":-1, | 256 "time_to_live_ms":-1, |
| 266 "large_image": {"url":"/logos/doodles/2015/some.gif"} | 257 "large_image": {"url":"/logos/doodles/2015/some.gif"} |
| 267 }})json"); | 258 }})json"); |
| 268 | 259 |
| 269 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); | 260 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); |
| 270 EXPECT_TRUE(response.has_value()); | 261 EXPECT_TRUE(response.has_value()); |
| 271 EXPECT_THAT(time_to_live, Eq(base::TimeDelta::FromMilliseconds(0))); | 262 EXPECT_THAT(time_to_live, Eq(base::TimeDelta::FromMilliseconds(0))); |
| 272 } | 263 } |
| 273 | 264 |
| 274 TEST_F(DoodleFetcherImplTest, DoodleExpiresImmediatelyWithoutValidTTL) { | 265 TEST_F(DoodleFetcherImplTest, DoodleExpiresImmediatelyWithoutValidTTL) { |
| 275 DoodleState state(DoodleState::NO_DOODLE); | 266 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 267 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 268 |
| 269 DoodleState state = DoodleState::NO_DOODLE; |
| 276 base::TimeDelta time_to_live; | 270 base::TimeDelta time_to_live; |
| 277 base::Optional<DoodleConfig> response; | 271 base::Optional<DoodleConfig> response; |
| 278 | 272 EXPECT_CALL(callback, Run(_, _, _)) |
| 279 doodle_fetcher()->FetchDoodle( | 273 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<1>(&time_to_live), |
| 280 CreateResponseSavingCallback(&state, &time_to_live, &response)); | 274 SaveArg<2>(&response))); |
| 281 RespondWithData(R"json({"ddljson": { | 275 RespondWithData(R"json({"ddljson": { |
| 282 "large_image": {"url":"/logos/doodles/2015/some.gif"} | 276 "large_image": {"url":"/logos/doodles/2015/some.gif"} |
| 283 }})json"); | 277 }})json"); |
| 284 | 278 |
| 285 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); | 279 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); |
| 286 EXPECT_TRUE(response.has_value()); | 280 EXPECT_TRUE(response.has_value()); |
| 287 EXPECT_THAT(time_to_live, Eq(base::TimeDelta::FromMilliseconds(0))); | 281 EXPECT_THAT(time_to_live, Eq(base::TimeDelta::FromMilliseconds(0))); |
| 288 } | 282 } |
| 289 | 283 |
| 290 TEST_F(DoodleFetcherImplTest, ReturnsNoDoodleForMissingLargeImageUrl) { | 284 TEST_F(DoodleFetcherImplTest, ReturnsNoDoodleForMissingLargeImageUrl) { |
| 291 DoodleState state(DoodleState::AVAILABLE); | 285 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 286 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 287 |
| 288 DoodleState state = DoodleState::AVAILABLE; |
| 292 base::Optional<DoodleConfig> response; | 289 base::Optional<DoodleConfig> response; |
| 293 | 290 EXPECT_CALL(callback, Run(_, _, _)) |
| 294 doodle_fetcher()->FetchDoodle( | 291 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<2>(&response))); |
| 295 CreateResponseSavingCallback(&state, nullptr, &response)); | |
| 296 RespondWithData(R"json({"ddljson": { | 292 RespondWithData(R"json({"ddljson": { |
| 297 "time_to_live_ms":55000, | 293 "time_to_live_ms":55000, |
| 298 "large_image": {} | 294 "large_image": {} |
| 299 }})json"); | 295 }})json"); |
| 300 | 296 |
| 301 EXPECT_THAT(state, Eq(DoodleState::NO_DOODLE)); | 297 EXPECT_THAT(state, Eq(DoodleState::NO_DOODLE)); |
| 302 EXPECT_FALSE(response.has_value()); | 298 EXPECT_FALSE(response.has_value()); |
| 303 } | 299 } |
| 304 | 300 |
| 305 TEST_F(DoodleFetcherImplTest, EmptyResponsesCausesNoDoodleState) { | 301 TEST_F(DoodleFetcherImplTest, EmptyResponsesCausesNoDoodleState) { |
| 306 DoodleState state(DoodleState::AVAILABLE); | 302 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 303 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 304 |
| 305 DoodleState state = DoodleState::AVAILABLE; |
| 307 base::Optional<DoodleConfig> response; | 306 base::Optional<DoodleConfig> response; |
| 308 | 307 EXPECT_CALL(callback, Run(_, _, _)) |
| 309 doodle_fetcher()->FetchDoodle( | 308 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<2>(&response))); |
| 310 CreateResponseSavingCallback(&state, nullptr, &response)); | |
| 311 RespondWithData("{\"ddljson\":{}}"); | 309 RespondWithData("{\"ddljson\":{}}"); |
| 312 | 310 |
| 313 EXPECT_THAT(state, Eq(DoodleState::NO_DOODLE)); | 311 EXPECT_THAT(state, Eq(DoodleState::NO_DOODLE)); |
| 314 EXPECT_FALSE(response.has_value()); | 312 EXPECT_FALSE(response.has_value()); |
| 315 } | 313 } |
| 316 | 314 |
| 317 TEST_F(DoodleFetcherImplTest, ResponseContainsExactlyTheSampleImages) { | 315 TEST_F(DoodleFetcherImplTest, ResponseContainsExactlyTheSampleImages) { |
| 318 DoodleState state(DoodleState::NO_DOODLE); | 316 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 317 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 318 |
| 319 DoodleState state = DoodleState::NO_DOODLE; |
| 319 base::Optional<DoodleConfig> response; | 320 base::Optional<DoodleConfig> response; |
| 320 | 321 EXPECT_CALL(callback, Run(_, _, _)) |
| 321 doodle_fetcher()->FetchDoodle( | 322 .WillOnce(DoAll(SaveArg<0>(&state), SaveArg<2>(&response))); |
| 322 CreateResponseSavingCallback(&state, nullptr, &response)); | |
| 323 RespondWithData(R"json()]}'{ | 323 RespondWithData(R"json()]}'{ |
| 324 "ddljson": { | 324 "ddljson": { |
| 325 "time_to_live_ms":55000, | 325 "time_to_live_ms":55000, |
| 326 "large_image": { | 326 "large_image": { |
| 327 "height":225, | 327 "height":225, |
| 328 "is_animated_gif":true, | 328 "is_animated_gif":true, |
| 329 "is_cta":false, | 329 "is_cta":false, |
| 330 "url":"/logos/doodles/2015/new-years-eve-2015-59854387958251-hp.gif", | 330 "url":"/logos/doodles/2015/new-years-eve-2015-59854387958251-hp.gif", |
| 331 "width":489 | 331 "width":489 |
| 332 }, | 332 }, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 344 "url":"/logos/doodles/2015/new-years-eve-2015-59854387958251-thp.png", | 344 "url":"/logos/doodles/2015/new-years-eve-2015-59854387958251-thp.png", |
| 345 "width":510 | 345 "width":510 |
| 346 } | 346 } |
| 347 }})json"); | 347 }})json"); |
| 348 | 348 |
| 349 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); | 349 EXPECT_THAT(state, Eq(DoodleState::AVAILABLE)); |
| 350 ASSERT_TRUE(response.has_value()); | 350 ASSERT_TRUE(response.has_value()); |
| 351 DoodleConfig config = response.value(); | 351 DoodleConfig config = response.value(); |
| 352 | 352 |
| 353 EXPECT_TRUE(config.large_image.url.is_valid()); | 353 EXPECT_TRUE(config.large_image.url.is_valid()); |
| 354 EXPECT_THAT(config.large_image.url.spec(), | 354 EXPECT_THAT(config.large_image.url, |
| 355 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" | 355 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" |
| 356 "8251-hp.gif"))); | 356 "8251-hp.gif"))); |
| 357 EXPECT_THAT(config.large_image.width, Eq(489)); | 357 EXPECT_THAT(config.large_image.width, Eq(489)); |
| 358 EXPECT_THAT(config.large_image.height, Eq(225)); | 358 EXPECT_THAT(config.large_image.height, Eq(225)); |
| 359 EXPECT_TRUE(config.large_image.is_animated_gif); | 359 EXPECT_TRUE(config.large_image.is_animated_gif); |
| 360 EXPECT_FALSE(config.large_image.is_cta); | 360 EXPECT_FALSE(config.large_image.is_cta); |
| 361 | 361 |
| 362 ASSERT_TRUE(config.transparent_large_image.has_value()); | 362 ASSERT_TRUE(config.transparent_large_image.has_value()); |
| 363 EXPECT_TRUE(config.transparent_large_image->url.is_valid()); | 363 EXPECT_TRUE(config.transparent_large_image->url.is_valid()); |
| 364 EXPECT_THAT(config.transparent_large_image->url.spec(), | 364 EXPECT_THAT(config.transparent_large_image->url, |
| 365 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" | 365 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" |
| 366 "8251-thp.png"))); | 366 "8251-thp.png"))); |
| 367 EXPECT_THAT(config.transparent_large_image->width, Eq(510)); | 367 EXPECT_THAT(config.transparent_large_image->width, Eq(510)); |
| 368 EXPECT_THAT(config.transparent_large_image->height, Eq(225)); | 368 EXPECT_THAT(config.transparent_large_image->height, Eq(225)); |
| 369 EXPECT_FALSE(config.transparent_large_image->is_animated_gif); | 369 EXPECT_FALSE(config.transparent_large_image->is_animated_gif); |
| 370 EXPECT_FALSE(config.transparent_large_image->is_cta); | 370 EXPECT_FALSE(config.transparent_large_image->is_cta); |
| 371 | 371 |
| 372 ASSERT_TRUE(config.large_cta_image.has_value()); | 372 ASSERT_TRUE(config.large_cta_image.has_value()); |
| 373 EXPECT_TRUE(config.large_cta_image->url.is_valid()); | 373 EXPECT_TRUE(config.large_cta_image->url.is_valid()); |
| 374 EXPECT_THAT(config.large_cta_image->url.spec(), | 374 EXPECT_THAT(config.large_cta_image->url, |
| 375 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" | 375 Eq(Resolve("/logos/doodles/2015/new-years-eve-2015-5985438795" |
| 376 "8251-cta.gif"))); | 376 "8251-cta.gif"))); |
| 377 EXPECT_THAT(config.large_cta_image->width, Eq(489)); | 377 EXPECT_THAT(config.large_cta_image->width, Eq(489)); |
| 378 EXPECT_THAT(config.large_cta_image->height, Eq(225)); | 378 EXPECT_THAT(config.large_cta_image->height, Eq(225)); |
| 379 EXPECT_TRUE(config.large_cta_image->is_animated_gif); | 379 EXPECT_TRUE(config.large_cta_image->is_animated_gif); |
| 380 EXPECT_TRUE(config.large_cta_image->is_cta); | 380 EXPECT_TRUE(config.large_cta_image->is_cta); |
| 381 } | 381 } |
| 382 | 382 |
| 383 TEST_F(DoodleFetcherImplTest, RespondsToMultipleRequestsWithSameFetcher) { | 383 TEST_F(DoodleFetcherImplTest, RespondsToMultipleRequestsWithSameFetcher) { |
| 384 DoodleState state1(DoodleState::NO_DOODLE); | |
| 385 DoodleState state2(DoodleState::NO_DOODLE); | |
| 386 base::Optional<DoodleConfig> response1; | |
| 387 base::Optional<DoodleConfig> response2; | |
| 388 | |
| 389 // Trigger two requests. | 384 // Trigger two requests. |
| 390 doodle_fetcher()->FetchDoodle( | 385 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback1; |
| 391 CreateResponseSavingCallback(&state1, nullptr, &response1)); | 386 doodle_fetcher()->FetchDoodle(callback1.Get()); |
| 392 net::URLFetcher* first_created_fetcher = GetRunningFetcher(); | 387 net::URLFetcher* first_created_fetcher = GetRunningFetcher(); |
| 393 doodle_fetcher()->FetchDoodle( | 388 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback2; |
| 394 CreateResponseSavingCallback(&state2, nullptr, &response2)); | 389 doodle_fetcher()->FetchDoodle(callback2.Get()); |
| 395 net::URLFetcher* second_created_fetcher = GetRunningFetcher(); | 390 net::URLFetcher* second_created_fetcher = GetRunningFetcher(); |
| 396 | 391 |
| 397 // Expect that only one fetcher handles both requests. | 392 // Expect that only one fetcher handles both requests. |
| 398 EXPECT_THAT(first_created_fetcher, Eq(second_created_fetcher)); | 393 EXPECT_THAT(first_created_fetcher, Eq(second_created_fetcher)); |
| 399 | 394 |
| 395 // But both callbacks should get called. |
| 396 DoodleState state1 = DoodleState::NO_DOODLE; |
| 397 DoodleState state2 = DoodleState::NO_DOODLE; |
| 398 base::Optional<DoodleConfig> response1; |
| 399 base::Optional<DoodleConfig> response2; |
| 400 |
| 401 EXPECT_CALL(callback1, Run(_, _, _)) |
| 402 .WillOnce(DoAll(SaveArg<0>(&state1), SaveArg<2>(&response1))); |
| 403 EXPECT_CALL(callback2, Run(_, _, _)) |
| 404 .WillOnce(DoAll(SaveArg<0>(&state2), SaveArg<2>(&response2))); |
| 405 |
| 400 RespondWithData(R"json({"ddljson": { | 406 RespondWithData(R"json({"ddljson": { |
| 401 "time_to_live_ms":55000, | 407 "time_to_live_ms":55000, |
| 402 "large_image": {"url":"/logos/doodles/2015/some.gif"} | 408 "large_image": {"url":"/logos/doodles/2015/some.gif"} |
| 403 }})json"); | 409 }})json"); |
| 404 | 410 |
| 405 // Ensure that both requests received a response. | 411 // Ensure that both requests received a response. |
| 406 EXPECT_THAT(state1, Eq(DoodleState::AVAILABLE)); | 412 EXPECT_THAT(state1, Eq(DoodleState::AVAILABLE)); |
| 407 EXPECT_TRUE(response1.has_value()); | 413 EXPECT_TRUE(response1.has_value()); |
| 408 EXPECT_THAT(state2, Eq(DoodleState::AVAILABLE)); | 414 EXPECT_THAT(state2, Eq(DoodleState::AVAILABLE)); |
| 409 EXPECT_TRUE(response2.has_value()); | 415 EXPECT_TRUE(response2.has_value()); |
| 410 } | 416 } |
| 411 | 417 |
| 412 TEST_F(DoodleFetcherImplTest, ReceivesBaseUrlFromTracker) { | 418 TEST_F(DoodleFetcherImplTest, ReceivesBaseUrlFromTracker) { |
| 413 doodle_fetcher()->FetchDoodle(CreateResponseSavingCallback( | 419 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 414 /*state=*/nullptr, nullptr, /*response=*/nullptr)); | 420 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 415 | 421 |
| 422 // TODO(treib,fhorschig): This doesn't really test anything useful, since the |
| 423 // Google base URL is the default anyway. Find a way to set the base URL in |
| 424 // the tracker. |
| 416 EXPECT_THAT(GetRunningFetcher()->GetOriginalURL(), | 425 EXPECT_THAT(GetRunningFetcher()->GetOriginalURL(), |
| 417 Eq(GetGoogleBaseURL().Resolve(kDoodleConfigPath))); | 426 Eq(GetGoogleBaseURL().Resolve(kDoodleConfigPath))); |
| 418 } | 427 } |
| 419 | 428 |
| 420 TEST_F(DoodleFetcherImplTest, OverridesBaseUrlWithCommandLineArgument) { | 429 TEST_F(DoodleFetcherImplTest, OverridesBaseUrlWithCommandLineArgument) { |
| 421 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( | 430 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
| 422 switches::kGoogleBaseURL, "http://www.google.kz"); | 431 switches::kGoogleBaseURL, "http://www.google.kz"); |
| 423 | 432 |
| 424 doodle_fetcher()->FetchDoodle(CreateResponseSavingCallback( | 433 base::MockCallback<DoodleFetcherImpl::FinishedCallback> callback; |
| 425 /*state=*/nullptr, nullptr, /*response=*/nullptr)); | 434 doodle_fetcher()->FetchDoodle(callback.Get()); |
| 426 | 435 |
| 427 EXPECT_THAT(GetRunningFetcher()->GetOriginalURL(), | 436 EXPECT_THAT(GetRunningFetcher()->GetOriginalURL(), |
| 428 Eq(GURL("http://www.google.kz").Resolve(kDoodleConfigPath))); | 437 Eq(GURL("http://www.google.kz").Resolve(kDoodleConfigPath))); |
| 429 } | 438 } |
| 430 | 439 |
| 431 } // namespace doodle | 440 } // namespace doodle |
| OLD | NEW |