Update V8 to version 4.5.80.
[chromium-blink-merge.git] / chromeos / timezone / timezone_unittest.cc
blob9e05fe0e8670e846b9767c024129a638c8fdf032
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/message_loop/message_loop.h"
6 #include "base/run_loop.h"
7 #include "chromeos/geolocation/geoposition.h"
8 #include "chromeos/timezone/timezone_provider.h"
9 #include "chromeos/timezone/timezone_resolver.h"
10 #include "net/http/http_response_headers.h"
11 #include "net/http/http_status_code.h"
12 #include "net/url_request/test_url_fetcher_factory.h"
13 #include "net/url_request/url_fetcher_impl.h"
14 #include "net/url_request/url_request_status.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 namespace {
19 const int kRequestRetryIntervalMilliSeconds = 200;
21 // This should be different from default to prevent TimeZoneRequest
22 // from modifying it.
23 const char kTestTimeZoneProviderUrl[] =
24 "https://localhost/maps/api/timezone/json?";
26 const char kSimpleResponseBody[] =
27 "{\n"
28 " \"dstOffset\" : 0.0,\n"
29 " \"rawOffset\" : -28800.0,\n"
30 " \"status\" : \"OK\",\n"
31 " \"timeZoneId\" : \"America/Los_Angeles\",\n"
32 " \"timeZoneName\" : \"Pacific Standard Time\"\n"
33 "}";
35 struct SimpleRequest {
36 SimpleRequest()
37 : url("https://localhost/maps/api/timezone/"
38 "json?location=39.603481,-119.682251&timestamp=1331161200&sensor="
39 "false"),
40 http_response(kSimpleResponseBody) {
41 position.latitude = 39.6034810;
42 position.longitude = -119.6822510;
43 position.accuracy = 1;
44 position.error_code = 0;
45 position.timestamp = base::Time::FromTimeT(1331161200);
46 position.status = chromeos::Geoposition::STATUS_NONE;
47 EXPECT_EQ(
48 "latitude=39.603481, longitude=-119.682251, accuracy=1.000000, "
49 "error_code=0, error_message='', status=0 (NONE)",
50 position.ToString());
52 timezone.dstOffset = 0;
53 timezone.rawOffset = -28800;
54 timezone.timeZoneId = "America/Los_Angeles";
55 timezone.timeZoneName = "Pacific Standard Time";
56 timezone.error_message.erase();
57 timezone.status = chromeos::TimeZoneResponseData::OK;
58 EXPECT_EQ(
59 "dstOffset=0.000000, rawOffset=-28800.000000, "
60 "timeZoneId='America/Los_Angeles', timeZoneName='Pacific Standard "
61 "Time', error_message='', status=0 (OK)",
62 timezone.ToStringForDebug());
65 GURL url;
66 chromeos::Geoposition position;
67 std::string http_response;
68 chromeos::TimeZoneResponseData timezone;
71 } // anonymous namespace
73 namespace chromeos {
75 // This is helper class for net::FakeURLFetcherFactory.
76 class TestTimeZoneAPIURLFetcherCallback {
77 public:
78 TestTimeZoneAPIURLFetcherCallback(const GURL& url,
79 const size_t require_retries,
80 const std::string& response,
81 TimeZoneProvider* provider)
82 : url_(url),
83 require_retries_(require_retries),
84 response_(response),
85 factory_(NULL),
86 attempts_(0),
87 provider_(provider) {}
89 scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
90 const GURL& url,
91 net::URLFetcherDelegate* delegate,
92 const std::string& response_data,
93 net::HttpStatusCode response_code,
94 net::URLRequestStatus::Status status) {
95 EXPECT_EQ(provider_->requests_.size(), 1U);
97 TimeZoneRequest* timezone_request = provider_->requests_[0];
99 const base::TimeDelta base_retry_interval =
100 base::TimeDelta::FromMilliseconds(kRequestRetryIntervalMilliSeconds);
101 timezone_request->set_retry_sleep_on_server_error_for_testing(
102 base_retry_interval);
103 timezone_request->set_retry_sleep_on_bad_response_for_testing(
104 base_retry_interval);
106 ++attempts_;
107 if (attempts_ > require_retries_) {
108 response_code = net::HTTP_OK;
109 status = net::URLRequestStatus::SUCCESS;
110 factory_->SetFakeResponse(url, response_, response_code, status);
112 scoped_ptr<net::FakeURLFetcher> fetcher(new net::FakeURLFetcher(
113 url, delegate, response_, response_code, status));
114 scoped_refptr<net::HttpResponseHeaders> download_headers =
115 new net::HttpResponseHeaders(std::string());
116 download_headers->AddHeader("Content-Type: application/json");
117 fetcher->set_response_headers(download_headers);
118 return fetcher.Pass();
121 void Initialize(net::FakeURLFetcherFactory* factory) {
122 factory_ = factory;
123 factory_->SetFakeResponse(url_,
124 std::string(),
125 net::HTTP_INTERNAL_SERVER_ERROR,
126 net::URLRequestStatus::FAILED);
129 size_t attempts() const { return attempts_; }
131 private:
132 const GURL url_;
133 // Respond with OK on required retry attempt.
134 const size_t require_retries_;
135 std::string response_;
136 net::FakeURLFetcherFactory* factory_;
137 size_t attempts_;
138 TimeZoneProvider* provider_;
140 DISALLOW_COPY_AND_ASSIGN(TestTimeZoneAPIURLFetcherCallback);
143 // This implements fake TimeZone API remote endpoint.
144 // Response data is served to TimeZoneProvider via
145 // net::FakeURLFetcher.
146 class TimeZoneAPIFetcherFactory {
147 public:
148 TimeZoneAPIFetcherFactory(const GURL& url,
149 const std::string& response,
150 const size_t require_retries,
151 TimeZoneProvider* provider) {
152 url_callback_.reset(new TestTimeZoneAPIURLFetcherCallback(
153 url, require_retries, response, provider));
154 net::URLFetcherImpl::set_factory(NULL);
155 fetcher_factory_.reset(new net::FakeURLFetcherFactory(
156 NULL,
157 base::Bind(&TestTimeZoneAPIURLFetcherCallback::CreateURLFetcher,
158 base::Unretained(url_callback_.get()))));
159 url_callback_->Initialize(fetcher_factory_.get());
162 size_t attempts() const { return url_callback_->attempts(); }
164 private:
165 scoped_ptr<TestTimeZoneAPIURLFetcherCallback> url_callback_;
166 scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory_;
168 DISALLOW_COPY_AND_ASSIGN(TimeZoneAPIFetcherFactory);
171 class TimeZoneReceiver {
172 public:
173 TimeZoneReceiver() : server_error_(false) {}
175 void OnRequestDone(scoped_ptr<TimeZoneResponseData> timezone,
176 bool server_error) {
177 timezone_ = timezone.Pass();
178 server_error_ = server_error;
180 message_loop_runner_->Quit();
183 void WaitUntilRequestDone() {
184 message_loop_runner_.reset(new base::RunLoop);
185 message_loop_runner_->Run();
188 const TimeZoneResponseData* timezone() const { return timezone_.get(); }
189 bool server_error() const { return server_error_; }
191 private:
192 scoped_ptr<TimeZoneResponseData> timezone_;
193 bool server_error_;
194 scoped_ptr<base::RunLoop> message_loop_runner_;
197 class TimeZoneTest : public testing::Test {
198 private:
199 base::MessageLoop message_loop_;
202 TEST_F(TimeZoneTest, ResponseOK) {
203 TimeZoneProvider provider(NULL, GURL(kTestTimeZoneProviderUrl));
204 const SimpleRequest simple_request;
206 TimeZoneAPIFetcherFactory url_factory(simple_request.url,
207 simple_request.http_response,
208 0 /* require_retries */,
209 &provider);
211 TimeZoneReceiver receiver;
213 provider.RequestTimezone(simple_request.position,
214 base::TimeDelta::FromSeconds(1),
215 base::Bind(&TimeZoneReceiver::OnRequestDone,
216 base::Unretained(&receiver)));
217 receiver.WaitUntilRequestDone();
219 EXPECT_EQ(simple_request.timezone.ToStringForDebug(),
220 receiver.timezone()->ToStringForDebug());
221 EXPECT_FALSE(receiver.server_error());
222 EXPECT_EQ(1U, url_factory.attempts());
225 TEST_F(TimeZoneTest, ResponseOKWithRetries) {
226 TimeZoneProvider provider(NULL, GURL(kTestTimeZoneProviderUrl));
227 const SimpleRequest simple_request;
229 TimeZoneAPIFetcherFactory url_factory(simple_request.url,
230 simple_request.http_response,
231 3 /* require_retries */,
232 &provider);
234 TimeZoneReceiver receiver;
236 provider.RequestTimezone(simple_request.position,
237 base::TimeDelta::FromSeconds(1),
238 base::Bind(&TimeZoneReceiver::OnRequestDone,
239 base::Unretained(&receiver)));
240 receiver.WaitUntilRequestDone();
241 EXPECT_EQ(simple_request.timezone.ToStringForDebug(),
242 receiver.timezone()->ToStringForDebug());
243 EXPECT_FALSE(receiver.server_error());
244 EXPECT_EQ(4U, url_factory.attempts());
247 TEST_F(TimeZoneTest, InvalidResponse) {
248 TimeZoneProvider provider(NULL, GURL(kTestTimeZoneProviderUrl));
249 const SimpleRequest simple_request;
251 TimeZoneAPIFetcherFactory url_factory(simple_request.url,
252 "invalid JSON string",
253 0 /* require_retries */,
254 &provider);
256 TimeZoneReceiver receiver;
258 const int timeout_seconds = 1;
259 size_t expected_retries = static_cast<size_t>(
260 timeout_seconds * 1000 / kRequestRetryIntervalMilliSeconds);
261 ASSERT_GE(expected_retries, 2U);
263 provider.RequestTimezone(simple_request.position,
264 base::TimeDelta::FromSeconds(timeout_seconds),
265 base::Bind(&TimeZoneReceiver::OnRequestDone,
266 base::Unretained(&receiver)));
267 receiver.WaitUntilRequestDone();
268 EXPECT_EQ(
269 "dstOffset=0.000000, rawOffset=0.000000, timeZoneId='', timeZoneName='', "
270 "error_message='TimeZone provider at 'https://localhost/' : JSONReader "
271 "failed: Line: 1, column: 1, Unexpected token..', status=6 "
272 "(REQUEST_ERROR)",
273 receiver.timezone()->ToStringForDebug());
274 EXPECT_FALSE(receiver.server_error());
275 EXPECT_GE(url_factory.attempts(), 2U);
276 if (url_factory.attempts() > expected_retries + 1) {
277 LOG(WARNING) << "TimeZoneTest::InvalidResponse: Too many attempts ("
278 << url_factory.attempts() << "), no more then "
279 << expected_retries + 1 << " expected.";
281 if (url_factory.attempts() < expected_retries - 1) {
282 LOG(WARNING) << "TimeZoneTest::InvalidResponse: Too less attempts ("
283 << url_factory.attempts() << "), greater then "
284 << expected_retries - 1 << " expected.";
288 TEST(TimeZoneResolverTest, CheckIntervals) {
289 for (int requests_count = 1; requests_count < 10; ++requests_count) {
290 EXPECT_EQ(requests_count,
291 TimeZoneResolver::MaxRequestsCountForIntervalForTesting(
292 TimeZoneResolver::IntervalForNextRequestForTesting(
293 requests_count)));
297 } // namespace chromeos