aw: Rendering test harness and end-to-end smoke test
[chromium-blink-merge.git] / content / browser / geolocation / geolocation_provider_impl_unittest.cc
blobf201f48e842241d7866c167feb49926dc97369ef
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/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string16.h"
11 #include "base/time/time.h"
12 #include "content/browser/geolocation/geolocation_provider_impl.h"
13 #include "content/browser/geolocation/mock_location_arbitrator.h"
14 #include "content/public/browser/access_token_store.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/test/test_browser_thread.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using testing::MakeMatcher;
21 using testing::Matcher;
22 using testing::MatcherInterface;
23 using testing::MatchResultListener;
25 namespace content {
27 class LocationProviderForTestArbitrator : public GeolocationProviderImpl {
28 public:
29 LocationProviderForTestArbitrator() : mock_arbitrator_(NULL) {}
30 ~LocationProviderForTestArbitrator() override {}
32 // Only valid for use on the geolocation thread.
33 MockLocationArbitrator* mock_arbitrator() const {
34 return mock_arbitrator_;
37 protected:
38 // GeolocationProviderImpl implementation:
39 LocationArbitrator* CreateArbitrator() override;
41 private:
42 MockLocationArbitrator* mock_arbitrator_;
45 LocationArbitrator* LocationProviderForTestArbitrator::CreateArbitrator() {
46 DCHECK(mock_arbitrator_ == NULL);
47 mock_arbitrator_ = new MockLocationArbitrator;
48 return mock_arbitrator_;
51 class GeolocationObserver {
52 public:
53 virtual ~GeolocationObserver() {}
54 virtual void OnLocationUpdate(const Geoposition& position) = 0;
57 class MockGeolocationObserver : public GeolocationObserver {
58 public:
59 MOCK_METHOD1(OnLocationUpdate, void(const Geoposition& position));
62 class AsyncMockGeolocationObserver : public MockGeolocationObserver {
63 public:
64 void OnLocationUpdate(const Geoposition& position) override {
65 MockGeolocationObserver::OnLocationUpdate(position);
66 base::MessageLoop::current()->Quit();
70 class MockGeolocationCallbackWrapper {
71 public:
72 MOCK_METHOD1(Callback, void(const Geoposition& position));
75 class GeopositionEqMatcher
76 : public MatcherInterface<const Geoposition&> {
77 public:
78 explicit GeopositionEqMatcher(const Geoposition& expected)
79 : expected_(expected) {}
81 virtual bool MatchAndExplain(const Geoposition& actual,
82 MatchResultListener* listener) const override {
83 return actual.latitude == expected_.latitude &&
84 actual.longitude == expected_.longitude &&
85 actual.altitude == expected_.altitude &&
86 actual.accuracy == expected_.accuracy &&
87 actual.altitude_accuracy == expected_.altitude_accuracy &&
88 actual.heading == expected_.heading &&
89 actual.speed == expected_.speed &&
90 actual.timestamp == expected_.timestamp &&
91 actual.error_code == expected_.error_code &&
92 actual.error_message == expected_.error_message;
95 virtual void DescribeTo(::std::ostream* os) const override {
96 *os << "which matches the expected position";
99 virtual void DescribeNegationTo(::std::ostream* os) const override {
100 *os << "which does not match the expected position";
103 private:
104 Geoposition expected_;
106 DISALLOW_COPY_AND_ASSIGN(GeopositionEqMatcher);
109 Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) {
110 return MakeMatcher(new GeopositionEqMatcher(expected));
113 class GeolocationProviderTest : public testing::Test {
114 protected:
115 GeolocationProviderTest()
116 : message_loop_(),
117 ui_thread_(BrowserThread::UI, &message_loop_),
118 provider_(new LocationProviderForTestArbitrator) {
121 ~GeolocationProviderTest() override {}
123 LocationProviderForTestArbitrator* provider() { return provider_.get(); }
125 // Called on test thread.
126 bool ProvidersStarted();
127 void SendMockLocation(const Geoposition& position);
129 private:
130 // Called on provider thread.
131 void GetProvidersStarted(bool* started);
133 base::MessageLoop message_loop_;
134 TestBrowserThread ui_thread_;
135 scoped_ptr<LocationProviderForTestArbitrator> provider_;
139 bool GeolocationProviderTest::ProvidersStarted() {
140 DCHECK(provider_->IsRunning());
141 DCHECK(base::MessageLoop::current() == &message_loop_);
142 bool started;
143 provider_->message_loop_proxy()->PostTaskAndReply(
144 FROM_HERE,
145 base::Bind(&GeolocationProviderTest::GetProvidersStarted,
146 base::Unretained(this),
147 &started),
148 base::MessageLoop::QuitClosure());
149 message_loop_.Run();
150 return started;
153 void GeolocationProviderTest::GetProvidersStarted(bool* started) {
154 DCHECK(base::MessageLoop::current() == provider_->message_loop());
155 *started = provider_->mock_arbitrator()->providers_started();
158 void GeolocationProviderTest::SendMockLocation(const Geoposition& position) {
159 DCHECK(provider_->IsRunning());
160 DCHECK(base::MessageLoop::current() == &message_loop_);
161 provider_->message_loop()
162 ->PostTask(FROM_HERE,
163 base::Bind(&GeolocationProviderImpl::OnLocationUpdate,
164 base::Unretained(provider_.get()),
165 position));
168 // Regression test for http://crbug.com/59377
169 TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) {
170 EXPECT_FALSE(provider()->user_did_opt_into_location_services_for_testing());
171 provider()->UserDidOptIntoLocationServices();
172 EXPECT_TRUE(provider()->user_did_opt_into_location_services_for_testing());
175 void DummyFunction(const Geoposition& position) {
178 TEST_F(GeolocationProviderTest, StartStop) {
179 EXPECT_FALSE(provider()->IsRunning());
180 GeolocationProviderImpl::LocationUpdateCallback callback =
181 base::Bind(&DummyFunction);
182 scoped_ptr<content::GeolocationProvider::Subscription> subscription =
183 provider()->AddLocationUpdateCallback(callback, false);
184 EXPECT_TRUE(provider()->IsRunning());
185 EXPECT_TRUE(ProvidersStarted());
187 subscription.reset();
189 EXPECT_FALSE(ProvidersStarted());
190 EXPECT_TRUE(provider()->IsRunning());
193 TEST_F(GeolocationProviderTest, StalePositionNotSent) {
194 Geoposition first_position;
195 first_position.latitude = 12;
196 first_position.longitude = 34;
197 first_position.accuracy = 56;
198 first_position.timestamp = base::Time::Now();
200 AsyncMockGeolocationObserver first_observer;
201 GeolocationProviderImpl::LocationUpdateCallback first_callback = base::Bind(
202 &MockGeolocationObserver::OnLocationUpdate,
203 base::Unretained(&first_observer));
204 EXPECT_CALL(first_observer, OnLocationUpdate(GeopositionEq(first_position)));
205 scoped_ptr<content::GeolocationProvider::Subscription> subscription =
206 provider()->AddLocationUpdateCallback(first_callback, false);
207 SendMockLocation(first_position);
208 base::MessageLoop::current()->Run();
210 subscription.reset();
212 Geoposition second_position;
213 second_position.latitude = 13;
214 second_position.longitude = 34;
215 second_position.accuracy = 56;
216 second_position.timestamp = base::Time::Now();
218 AsyncMockGeolocationObserver second_observer;
220 // After adding a second observer, check that no unexpected position update
221 // is sent.
222 EXPECT_CALL(second_observer, OnLocationUpdate(testing::_)).Times(0);
223 GeolocationProviderImpl::LocationUpdateCallback second_callback = base::Bind(
224 &MockGeolocationObserver::OnLocationUpdate,
225 base::Unretained(&second_observer));
226 scoped_ptr<content::GeolocationProvider::Subscription> subscription2 =
227 provider()->AddLocationUpdateCallback(second_callback, false);
228 base::MessageLoop::current()->RunUntilIdle();
230 // The second observer should receive the new position now.
231 EXPECT_CALL(second_observer,
232 OnLocationUpdate(GeopositionEq(second_position)));
233 SendMockLocation(second_position);
234 base::MessageLoop::current()->Run();
236 subscription2.reset();
237 EXPECT_FALSE(ProvidersStarted());
240 TEST_F(GeolocationProviderTest, OverrideLocationForTesting) {
241 Geoposition position;
242 position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
243 provider()->OverrideLocationForTesting(position);
244 // Adding an observer when the location is overridden should synchronously
245 // update the observer with our overridden position.
246 MockGeolocationObserver mock_observer;
247 EXPECT_CALL(mock_observer, OnLocationUpdate(GeopositionEq(position)));
248 GeolocationProviderImpl::LocationUpdateCallback callback = base::Bind(
249 &MockGeolocationObserver::OnLocationUpdate,
250 base::Unretained(&mock_observer));
251 scoped_ptr<content::GeolocationProvider::Subscription> subscription =
252 provider()->AddLocationUpdateCallback(callback, false);
253 subscription.reset();
254 // Wait for the providers to be stopped now that all clients are gone.
255 EXPECT_FALSE(ProvidersStarted());
258 } // namespace content