diff options
author | alemate@chromium.org <alemate@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-19 22:00:33 +0000 |
---|---|---|
committer | alemate@chromium.org <alemate@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-19 22:00:33 +0000 |
commit | 4e7fcd383bd764914b268ffb44d44794071408ad (patch) | |
tree | bef7277e250464156cf91b076f4beb311531f39a /chrome/browser/chromeos | |
parent | 6fc38e51d312607cf3d67d0cf17759b1d288f47f (diff) | |
download | chromium_src-4e7fcd383bd764914b268ffb44d44794071408ad.zip chromium_src-4e7fcd383bd764914b268ffb44d44794071408ad.tar.gz chromium_src-4e7fcd383bd764914b268ffb44d44794071408ad.tar.bz2 |
Add SimpleGeolocationTest unit test.
Add test for SimpleGeolocation.
BUG=245075
TEST=none
Review URL: https://codereview.chromium.org/289313005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271499 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos')
4 files changed, 262 insertions, 3 deletions
diff --git a/chrome/browser/chromeos/geolocation/simple_geolocation_provider.h b/chrome/browser/chromeos/geolocation/simple_geolocation_provider.h index a3e3d04..0b0cd81 100644 --- a/chrome/browser/chromeos/geolocation/simple_geolocation_provider.h +++ b/chrome/browser/chromeos/geolocation/simple_geolocation_provider.h @@ -41,6 +41,8 @@ class SimpleGeolocationProvider { static GURL DefaultGeolocationProviderURL(); private: + friend class TestGeolocationAPIURLFetcherCallback; + // Geolocation response callback. Deletes request from requests_. void OnGeolocationResponse( SimpleGeolocationRequest* request, diff --git a/chrome/browser/chromeos/geolocation/simple_geolocation_request.cc b/chrome/browser/chromeos/geolocation/simple_geolocation_request.cc index b3b8134..ca1e34a 100644 --- a/chrome/browser/chromeos/geolocation/simple_geolocation_request.cc +++ b/chrome/browser/chromeos/geolocation/simple_geolocation_request.cc @@ -205,6 +205,8 @@ bool ParseServerResponse(const GURL& server_url, // Ignore result (code defaults to zero). error_object->GetIntegerWithoutPathExpansion(kCodeString, &(position->error_code)); + } else { + position->error_message.erase(); } if (location_object) { @@ -272,6 +274,10 @@ SimpleGeolocationRequest::SimpleGeolocationRequest( base::TimeDelta timeout) : url_context_getter_(url_context_getter), service_url_(service_url), + retry_sleep_on_server_error_(base::TimeDelta::FromSeconds( + kResolveGeolocationRetrySleepOnServerErrorSeconds)), + retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds( + kResolveGeolocationRetrySleepBadResponseSeconds)), timeout_(timeout), retries_(0) { } @@ -314,9 +320,8 @@ void SimpleGeolocationRequest::MakeRequest(const ResponseCallback& callback) { } void SimpleGeolocationRequest::Retry(bool server_error) { - const base::TimeDelta delay = base::TimeDelta::FromSeconds( - server_error ? kResolveGeolocationRetrySleepOnServerErrorSeconds - : kResolveGeolocationRetrySleepBadResponseSeconds); + base::TimeDelta delay(server_error ? retry_sleep_on_server_error_ + : retry_sleep_on_bad_response_); request_scheduled_.Start( FROM_HERE, delay, this, &SimpleGeolocationRequest::StartRequest); } diff --git a/chrome/browser/chromeos/geolocation/simple_geolocation_request.h b/chrome/browser/chromeos/geolocation/simple_geolocation_request.h index 3cc47e3..f6baf4d 100644 --- a/chrome/browser/chromeos/geolocation/simple_geolocation_request.h +++ b/chrome/browser/chromeos/geolocation/simple_geolocation_request.h @@ -55,6 +55,16 @@ class SimpleGeolocationRequest : private net::URLFetcherDelegate { // request will be silently cancelled. void MakeRequest(const ResponseCallback& callback); + void set_retry_sleep_on_server_error_for_testing( + const base::TimeDelta value) { + retry_sleep_on_server_error_ = value; + } + + void set_retry_sleep_on_bad_response_for_testing( + const base::TimeDelta value) { + retry_sleep_on_bad_response_ = value; + } + private: // net::URLFetcherDelegate virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; @@ -86,6 +96,10 @@ class SimpleGeolocationRequest : private net::URLFetcherDelegate { // When request was actually started. base::Time request_started_at_; + base::TimeDelta retry_sleep_on_server_error_; + + base::TimeDelta retry_sleep_on_bad_response_; + const base::TimeDelta timeout_; // Pending retry. diff --git a/chrome/browser/chromeos/geolocation/simple_geolocation_unittest.cc b/chrome/browser/chromeos/geolocation/simple_geolocation_unittest.cc new file mode 100644 index 0000000..0137c4b --- /dev/null +++ b/chrome/browser/chromeos/geolocation/simple_geolocation_unittest.cc @@ -0,0 +1,238 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/run_loop.h" +#include "chrome/browser/chromeos/geolocation/simple_geolocation_provider.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_status_code.h" +#include "net/url_request/test_url_fetcher_factory.h" +#include "net/url_request/url_fetcher_impl.h" +#include "net/url_request/url_request_status.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const int kRequestRetryIntervalMilliSeconds = 200; + +// This should be different from default to prevent SimpleGeolocationRequest +// from modifying it. +const char kTestGeolocationProviderUrl[] = + "https://localhost/geolocation/v1/geolocate?"; + +const char kSimpleResponseBody[] = + "{\n" + " \"location\": {\n" + " \"lat\": 51.0,\n" + " \"lng\": -0.1\n" + " },\n" + " \"accuracy\": 1200.4\n" + "}"; +} // anonymous namespace + +namespace chromeos { + +// This is helper class for net::FakeURLFetcherFactory. +class TestGeolocationAPIURLFetcherCallback { + public: + TestGeolocationAPIURLFetcherCallback(const GURL& url, + const size_t require_retries, + const std::string& response, + SimpleGeolocationProvider* provider) + : url_(url), + require_retries_(require_retries), + response_(response), + factory_(NULL), + attempts_(0), + provider_(provider) {} + + scoped_ptr<net::FakeURLFetcher> CreateURLFetcher( + const GURL& url, + net::URLFetcherDelegate* delegate, + const std::string& response_data, + net::HttpStatusCode response_code, + net::URLRequestStatus::Status status) { + EXPECT_EQ(provider_->requests_.size(), 1U); + + SimpleGeolocationRequest* geolocation_request = provider_->requests_[0]; + + const base::TimeDelta base_retry_interval = + base::TimeDelta::FromMilliseconds(kRequestRetryIntervalMilliSeconds); + geolocation_request->set_retry_sleep_on_server_error_for_testing( + base_retry_interval); + geolocation_request->set_retry_sleep_on_bad_response_for_testing( + base_retry_interval); + + ++attempts_; + if (attempts_ > require_retries_) { + response_code = net::HTTP_OK; + status = net::URLRequestStatus::SUCCESS; + factory_->SetFakeResponse(url, response_, response_code, status); + } + scoped_ptr<net::FakeURLFetcher> fetcher(new net::FakeURLFetcher( + url, delegate, response_, response_code, status)); + scoped_refptr<net::HttpResponseHeaders> download_headers = + new net::HttpResponseHeaders(std::string()); + download_headers->AddHeader("Content-Type: application/json"); + fetcher->set_response_headers(download_headers); + return fetcher.Pass(); + } + + void Initialize(net::FakeURLFetcherFactory* factory) { + factory_ = factory; + factory_->SetFakeResponse(url_, + std::string(), + net::HTTP_INTERNAL_SERVER_ERROR, + net::URLRequestStatus::FAILED); + } + + size_t attempts() const { return attempts_; } + + private: + const GURL url_; + // Respond with OK on required retry attempt. + const size_t require_retries_; + std::string response_; + net::FakeURLFetcherFactory* factory_; + size_t attempts_; + SimpleGeolocationProvider* provider_; + + DISALLOW_COPY_AND_ASSIGN(TestGeolocationAPIURLFetcherCallback); +}; + +// This implements fake Google MAPS Geolocation API remote endpoint. +// Response data is served to SimpleGeolocationProvider via +// net::FakeURLFetcher. +class GeolocationAPIFetcherFactory { + public: + GeolocationAPIFetcherFactory(const GURL& url, + const std::string& response, + const size_t require_retries, + SimpleGeolocationProvider* provider) { + url_callback_.reset(new TestGeolocationAPIURLFetcherCallback( + url, require_retries, response, provider)); + net::URLFetcherImpl::set_factory(NULL); + fetcher_factory_.reset(new net::FakeURLFetcherFactory( + NULL, + base::Bind(&TestGeolocationAPIURLFetcherCallback::CreateURLFetcher, + base::Unretained(url_callback_.get())))); + url_callback_->Initialize(fetcher_factory_.get()); + } + + size_t attempts() const { return url_callback_->attempts(); } + + private: + scoped_ptr<TestGeolocationAPIURLFetcherCallback> url_callback_; + scoped_ptr<net::FakeURLFetcherFactory> fetcher_factory_; + + DISALLOW_COPY_AND_ASSIGN(GeolocationAPIFetcherFactory); +}; + +class GeolocationReceiver { + public: + GeolocationReceiver() : server_error_(false) {} + + void OnRequestDone(const Geoposition& position, + bool server_error, + const base::TimeDelta elapsed) { + position_ = position; + server_error_ = server_error; + elapsed_ = elapsed; + + message_loop_runner_->Quit(); + } + + void WaitUntilRequestDone() { + message_loop_runner_.reset(new base::RunLoop); + message_loop_runner_->Run(); + } + + const Geoposition& position() const { return position_; } + bool server_error() const { return server_error_; } + base::TimeDelta elapsed() const { return elapsed_; } + + private: + Geoposition position_; + bool server_error_; + base::TimeDelta elapsed_; + scoped_ptr<base::RunLoop> message_loop_runner_; +}; + +class SimpleGeolocationTest : public testing::Test { + private: + content::TestBrowserThreadBundle thread_bundle_; +}; + +TEST_F(SimpleGeolocationTest, ResponseOK) { + SimpleGeolocationProvider provider(NULL, GURL(kTestGeolocationProviderUrl)); + + GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl), + std::string(kSimpleResponseBody), + 0 /* require_retries */, + &provider); + + GeolocationReceiver receiver; + provider.RequestGeolocation(base::TimeDelta::FromSeconds(1), + base::Bind(&GeolocationReceiver::OnRequestDone, + base::Unretained(&receiver))); + receiver.WaitUntilRequestDone(); + + EXPECT_EQ( + "latitude=51.000000, longitude=-0.100000, accuracy=1200.400000, " + "error_code=0, error_message='', status=1 (OK)", + receiver.position().ToString()); + EXPECT_FALSE(receiver.server_error()); + EXPECT_EQ(1U, url_factory.attempts()); +} + +TEST_F(SimpleGeolocationTest, ResponseOKWithRetries) { + SimpleGeolocationProvider provider(NULL, GURL(kTestGeolocationProviderUrl)); + + GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl), + std::string(kSimpleResponseBody), + 3 /* require_retries */, + &provider); + + GeolocationReceiver receiver; + provider.RequestGeolocation(base::TimeDelta::FromSeconds(1), + base::Bind(&GeolocationReceiver::OnRequestDone, + base::Unretained(&receiver))); + receiver.WaitUntilRequestDone(); + EXPECT_EQ( + "latitude=51.000000, longitude=-0.100000, accuracy=1200.400000, " + "error_code=0, error_message='', status=1 (OK)", + receiver.position().ToString()); + EXPECT_FALSE(receiver.server_error()); + EXPECT_EQ(4U, url_factory.attempts()); +} + +TEST_F(SimpleGeolocationTest, InvalidResponse) { + SimpleGeolocationProvider provider(NULL, GURL(kTestGeolocationProviderUrl)); + + GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl), + "invalid JSON string", + 0 /* require_retries */, + &provider); + + GeolocationReceiver receiver; + const int timeout_seconds = 1; + provider.RequestGeolocation(base::TimeDelta::FromSeconds(timeout_seconds), + base::Bind(&GeolocationReceiver::OnRequestDone, + base::Unretained(&receiver))); + receiver.WaitUntilRequestDone(); + + EXPECT_EQ( + "latitude=200.000000, longitude=200.000000, accuracy=-1.000000, " + "error_code=0, error_message='SimpleGeolocation provider at " + "'https://localhost/' : JSONReader failed: Line: 1, column: 1, " + "Unexpected token..', status=4 (TIMEOUT)", + receiver.position().ToString()); + EXPECT_TRUE(receiver.server_error()); + size_t expected_retries = static_cast<size_t>( + timeout_seconds * 1000 / kRequestRetryIntervalMilliSeconds); + EXPECT_LE(url_factory.attempts(), expected_retries + 1); + EXPECT_GE(url_factory.attempts(), expected_retries - 1); +} + +} // namespace chromeos |