Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / chromeos / geolocation / simple_geolocation_unittest.cc
blobdb2243ac0f28cd7a4e6ce2c7951b725e9052172f
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/simple_geolocation_provider.h"
8 #include "net/http/http_response_headers.h"
9 #include "net/http/http_status_code.h"
10 #include "net/url_request/test_url_fetcher_factory.h"
11 #include "net/url_request/url_fetcher_impl.h"
12 #include "net/url_request/url_request_status.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace {
17 const int kRequestRetryIntervalMilliSeconds = 200;
19 // This should be different from default to prevent SimpleGeolocationRequest
20 // from modifying it.
21 const char kTestGeolocationProviderUrl[] =
22 "https://localhost/geolocation/v1/geolocate?";
24 const char kSimpleResponseBody[] =
25 "{\n"
26 " \"location\": {\n"
27 " \"lat\": 51.0,\n"
28 " \"lng\": -0.1\n"
29 " },\n"
30 " \"accuracy\": 1200.4\n"
31 "}";
32 } // anonymous namespace
34 namespace chromeos {
36 // This is helper class for net::FakeURLFetcherFactory.
37 class TestGeolocationAPIURLFetcherCallback {
38 public:
39 TestGeolocationAPIURLFetcherCallback(const GURL& url,
40 const size_t require_retries,
41 const std::string& response,
42 SimpleGeolocationProvider* provider)
43 : url_(url),
44 require_retries_(require_retries),
45 response_(response),
46 factory_(NULL),
47 attempts_(0),
48 provider_(provider) {}
50 scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
51 const GURL& url,
52 net::URLFetcherDelegate* delegate,
53 const std::string& response_data,
54 net::HttpStatusCode response_code,
55 net::URLRequestStatus::Status status) {
56 EXPECT_EQ(provider_->requests_.size(), 1U);
58 SimpleGeolocationRequest* geolocation_request = provider_->requests_[0];
60 const base::TimeDelta base_retry_interval =
61 base::TimeDelta::FromMilliseconds(kRequestRetryIntervalMilliSeconds);
62 geolocation_request->set_retry_sleep_on_server_error_for_testing(
63 base_retry_interval);
64 geolocation_request->set_retry_sleep_on_bad_response_for_testing(
65 base_retry_interval);
67 ++attempts_;
68 if (attempts_ > require_retries_) {
69 response_code = net::HTTP_OK;
70 status = net::URLRequestStatus::SUCCESS;
71 factory_->SetFakeResponse(url, response_, response_code, status);
73 scoped_ptr<net::FakeURLFetcher> fetcher(new net::FakeURLFetcher(
74 url, delegate, response_, response_code, status));
75 scoped_refptr<net::HttpResponseHeaders> download_headers =
76 new net::HttpResponseHeaders(std::string());
77 download_headers->AddHeader("Content-Type: application/json");
78 fetcher->set_response_headers(download_headers);
79 return fetcher.Pass();
82 void Initialize(net::FakeURLFetcherFactory* factory) {
83 factory_ = factory;
84 factory_->SetFakeResponse(url_,
85 std::string(),
86 net::HTTP_INTERNAL_SERVER_ERROR,
87 net::URLRequestStatus::FAILED);
90 size_t attempts() const { return attempts_; }
92 private:
93 const GURL url_;
94 // Respond with OK on required retry attempt.
95 const size_t require_retries_;
96 std::string response_;
97 net::FakeURLFetcherFactory* factory_;
98 size_t attempts_;
99 SimpleGeolocationProvider* provider_;
101 DISALLOW_COPY_AND_ASSIGN(TestGeolocationAPIURLFetcherCallback);
104 // This implements fake Google MAPS Geolocation API remote endpoint.
105 // Response data is served to SimpleGeolocationProvider via
106 // net::FakeURLFetcher.
107 class GeolocationAPIFetcherFactory {
108 public:
109 GeolocationAPIFetcherFactory(const GURL& url,
110 const std::string& response,
111 const size_t require_retries,
112 SimpleGeolocationProvider* provider) {
113 url_callback_.reset(new TestGeolocationAPIURLFetcherCallback(
114 url, require_retries, response, provider));
115 net::URLFetcherImpl::set_factory(NULL);
116 fetcher_factory_.reset(new net::FakeURLFetcherFactory(
117 NULL,
118 base::Bind(&TestGeolocationAPIURLFetcherCallback::CreateURLFetcher,
119 base::Unretained(url_callback_.get()))));
120 url_callback_->Initialize(fetcher_factory_.get());
123 size_t attempts() const { return url_callback_->attempts(); }
125 private:
126 scoped_ptr<TestGeolocationAPIURLFetcherCallback> url_callback_;
127 scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory_;
129 DISALLOW_COPY_AND_ASSIGN(GeolocationAPIFetcherFactory);
132 class GeolocationReceiver {
133 public:
134 GeolocationReceiver() : server_error_(false) {}
136 void OnRequestDone(const Geoposition& position,
137 bool server_error,
138 const base::TimeDelta elapsed) {
139 position_ = position;
140 server_error_ = server_error;
141 elapsed_ = elapsed;
143 message_loop_runner_->Quit();
146 void WaitUntilRequestDone() {
147 message_loop_runner_.reset(new base::RunLoop);
148 message_loop_runner_->Run();
151 const Geoposition& position() const { return position_; }
152 bool server_error() const { return server_error_; }
153 base::TimeDelta elapsed() const { return elapsed_; }
155 private:
156 Geoposition position_;
157 bool server_error_;
158 base::TimeDelta elapsed_;
159 scoped_ptr<base::RunLoop> message_loop_runner_;
162 class SimpleGeolocationTest : public testing::Test {
163 private:
164 base::MessageLoop message_loop_;
167 TEST_F(SimpleGeolocationTest, ResponseOK) {
168 SimpleGeolocationProvider provider(NULL, GURL(kTestGeolocationProviderUrl));
170 GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl),
171 std::string(kSimpleResponseBody),
172 0 /* require_retries */,
173 &provider);
175 GeolocationReceiver receiver;
176 provider.RequestGeolocation(base::TimeDelta::FromSeconds(1),
177 base::Bind(&GeolocationReceiver::OnRequestDone,
178 base::Unretained(&receiver)));
179 receiver.WaitUntilRequestDone();
181 EXPECT_EQ(
182 "latitude=51.000000, longitude=-0.100000, accuracy=1200.400000, "
183 "error_code=0, error_message='', status=1 (OK)",
184 receiver.position().ToString());
185 EXPECT_FALSE(receiver.server_error());
186 EXPECT_EQ(1U, url_factory.attempts());
189 TEST_F(SimpleGeolocationTest, ResponseOKWithRetries) {
190 SimpleGeolocationProvider provider(NULL, GURL(kTestGeolocationProviderUrl));
192 GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl),
193 std::string(kSimpleResponseBody),
194 3 /* require_retries */,
195 &provider);
197 GeolocationReceiver receiver;
198 provider.RequestGeolocation(base::TimeDelta::FromSeconds(1),
199 base::Bind(&GeolocationReceiver::OnRequestDone,
200 base::Unretained(&receiver)));
201 receiver.WaitUntilRequestDone();
202 EXPECT_EQ(
203 "latitude=51.000000, longitude=-0.100000, accuracy=1200.400000, "
204 "error_code=0, error_message='', status=1 (OK)",
205 receiver.position().ToString());
206 EXPECT_FALSE(receiver.server_error());
207 EXPECT_EQ(4U, url_factory.attempts());
210 TEST_F(SimpleGeolocationTest, InvalidResponse) {
211 SimpleGeolocationProvider provider(NULL, GURL(kTestGeolocationProviderUrl));
213 GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl),
214 "invalid JSON string",
215 0 /* require_retries */,
216 &provider);
218 GeolocationReceiver receiver;
220 const int timeout_seconds = 1;
221 size_t expected_retries = static_cast<size_t>(
222 timeout_seconds * 1000 / kRequestRetryIntervalMilliSeconds);
223 ASSERT_GE(expected_retries, 2U);
225 provider.RequestGeolocation(base::TimeDelta::FromSeconds(timeout_seconds),
226 base::Bind(&GeolocationReceiver::OnRequestDone,
227 base::Unretained(&receiver)));
228 receiver.WaitUntilRequestDone();
230 EXPECT_EQ(
231 "latitude=200.000000, longitude=200.000000, accuracy=-1.000000, "
232 "error_code=0, error_message='SimpleGeolocation provider at "
233 "'https://localhost/' : JSONReader failed: Line: 1, column: 1, "
234 "Unexpected token..', status=4 (TIMEOUT)",
235 receiver.position().ToString());
236 EXPECT_TRUE(receiver.server_error());
237 EXPECT_GE(url_factory.attempts(), 2U);
238 if (url_factory.attempts() > expected_retries + 1) {
239 LOG(WARNING)
240 << "SimpleGeolocationTest::InvalidResponse: Too many attempts ("
241 << url_factory.attempts() << "), no more then " << expected_retries + 1
242 << " expected.";
244 if (url_factory.attempts() < expected_retries - 1) {
245 LOG(WARNING)
246 << "SimpleGeolocationTest::InvalidResponse: Too little attempts ("
247 << url_factory.attempts() << "), greater then " << expected_retries - 1
248 << " expected.";
252 } // namespace chromeos