OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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. | |
4 | |
5 #include "base/memory/scoped_ptr.h" | |
6 #include "content/browser/geolocation/fake_access_token_store.h" | |
7 #include "content/browser/geolocation/geolocation_observer.h" | |
8 #include "content/browser/geolocation/location_arbitrator.h" | |
9 #include "content/browser/geolocation/location_provider.h" | |
10 #include "content/browser/geolocation/mock_location_provider.h" | |
11 #include "content/public/common/geoposition.h" | |
12 #include "testing/gmock/include/gmock/gmock.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 using ::testing::NiceMock; | |
16 | |
17 namespace content { | |
18 | |
19 class MockLocationObserver : public GeolocationObserver { | |
20 public: | |
21 void InvalidateLastPosition() { | |
22 last_position_.latitude = 100; | |
23 last_position_.error_code = Geoposition::ERROR_CODE_NONE; | |
24 ASSERT_FALSE(last_position_.Validate()); | |
25 } | |
26 // Delegate | |
27 virtual void OnLocationUpdate(const Geoposition& position) { | |
28 last_position_ = position; | |
29 } | |
30 | |
31 Geoposition last_position_; | |
32 }; | |
33 | |
34 double g_fake_time_now_secs = 1; | |
35 | |
36 base::Time GetTimeNowForTest() { | |
37 return base::Time::FromDoubleT(g_fake_time_now_secs); | |
38 } | |
39 | |
40 void AdvanceTimeNow(const base::TimeDelta& delta) { | |
41 g_fake_time_now_secs += delta.InSecondsF(); | |
42 } | |
43 | |
44 void SetPositionFix(MockLocationProvider* provider, | |
45 double latitude, | |
46 double longitude, | |
47 double accuracy) { | |
48 Geoposition position; | |
49 position.error_code = Geoposition::ERROR_CODE_NONE; | |
50 position.latitude = latitude; | |
51 position.longitude = longitude; | |
52 position.accuracy = accuracy; | |
53 position.timestamp = GetTimeNowForTest(); | |
54 ASSERT_TRUE(position.Validate()); | |
55 provider->HandlePositionChanged(position); | |
56 } | |
57 | |
58 void SetReferencePosition(MockLocationProvider* provider) { | |
59 SetPositionFix(provider, 51.0, -0.1, 400); | |
60 } | |
61 | |
62 namespace { | |
63 | |
64 class TestingGeolocationArbitrator : public GeolocationArbitrator { | |
65 public: | |
66 TestingGeolocationArbitrator( | |
67 GeolocationObserver* observer, | |
68 AccessTokenStore* access_token_store) | |
69 : GeolocationArbitrator(observer), | |
70 cell_(NULL), | |
71 gps_(NULL), | |
72 access_token_store_(access_token_store) { | |
73 } | |
74 | |
75 virtual base::Time GetTimeNow() const OVERRIDE { | |
76 return GetTimeNowForTest(); | |
77 } | |
78 | |
79 virtual AccessTokenStore* NewAccessTokenStore() OVERRIDE { | |
80 return access_token_store_.get(); | |
81 } | |
82 | |
83 virtual LocationProviderBase* NewNetworkLocationProvider( | |
84 AccessTokenStore* access_token_store, | |
85 net::URLRequestContextGetter* context, | |
86 const GURL& url, | |
87 const string16& access_token) OVERRIDE { | |
88 return new MockLocationProvider(&cell_); | |
89 } | |
90 | |
91 virtual LocationProviderBase* NewSystemLocationProvider() OVERRIDE { | |
92 return new MockLocationProvider(&gps_); | |
93 } | |
94 | |
95 // Two location providers, with nice short names to make the tests more | |
96 // readable. Note |gps_| will only be set when there is a high accuracy | |
97 // observer registered (and |cell_| when there's at least one observer of any | |
98 // type). | |
99 MockLocationProvider* cell_; | |
100 MockLocationProvider* gps_; | |
101 scoped_refptr<AccessTokenStore> access_token_store_; | |
102 }; | |
103 | |
104 } // namespace | |
105 | |
106 class GeolocationLocationArbitratorTest : public testing::Test { | |
107 protected: | |
108 // testing::Test | |
109 virtual void SetUp() { | |
110 access_token_store_ = new NiceMock<FakeAccessTokenStore>; | |
111 observer_.reset(new MockLocationObserver); | |
112 arbitrator_.reset(new TestingGeolocationArbitrator( | |
113 observer_.get(), access_token_store_.get())); | |
114 } | |
115 | |
116 // testing::Test | |
117 virtual void TearDown() { | |
118 } | |
119 | |
120 void CheckLastPositionInfo(double latitude, | |
121 double longitude, | |
122 double accuracy) { | |
123 Geoposition geoposition = observer_->last_position_; | |
124 EXPECT_TRUE(geoposition.Validate()); | |
125 EXPECT_DOUBLE_EQ(latitude, geoposition.latitude); | |
126 EXPECT_DOUBLE_EQ(longitude, geoposition.longitude); | |
127 EXPECT_DOUBLE_EQ(accuracy, geoposition.accuracy); | |
128 } | |
129 | |
130 base::TimeDelta SwitchOnFreshnessCliff() { | |
131 // Add 1, to ensure it meets any greater-than test. | |
132 return base::TimeDelta::FromMilliseconds( | |
133 GeolocationArbitrator::kFixStaleTimeoutMilliseconds + 1); | |
134 } | |
135 | |
136 MockLocationProvider* cell() { | |
137 return arbitrator_->cell_; | |
138 } | |
139 | |
140 MockLocationProvider* gps() { | |
141 return arbitrator_->gps_; | |
142 } | |
143 | |
144 scoped_refptr<FakeAccessTokenStore> access_token_store_; | |
145 scoped_ptr<MockLocationObserver> observer_; | |
146 scoped_ptr<TestingGeolocationArbitrator> arbitrator_; | |
147 MessageLoop loop_; | |
148 }; | |
149 | |
150 TEST_F(GeolocationLocationArbitratorTest, CreateDestroy) { | |
151 EXPECT_TRUE(access_token_store_); | |
152 EXPECT_TRUE(arbitrator_ != NULL); | |
153 arbitrator_.reset(); | |
154 SUCCEED(); | |
155 } | |
156 | |
157 TEST_F(GeolocationLocationArbitratorTest, OnPermissionGranted) { | |
158 EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted()); | |
159 arbitrator_->OnPermissionGranted(); | |
160 EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted()); | |
161 // Can't check the provider has been notified without going through the | |
162 // motions to create the provider (see next test). | |
163 EXPECT_FALSE(cell()); | |
164 EXPECT_FALSE(gps()); | |
165 } | |
166 | |
167 TEST_F(GeolocationLocationArbitratorTest, NormalUsage) { | |
168 ASSERT_TRUE(access_token_store_); | |
169 ASSERT_TRUE(arbitrator_ != NULL); | |
170 | |
171 EXPECT_FALSE(cell()); | |
172 EXPECT_FALSE(gps()); | |
173 arbitrator_->StartProviders(GeolocationObserverOptions(false)); | |
174 | |
175 EXPECT_TRUE(access_token_store_->access_token_set_.empty()); | |
176 EXPECT_TRUE(access_token_store_->access_token_set_.empty()); | |
177 | |
178 access_token_store_->NotifyDelegateTokensLoaded(); | |
179 ASSERT_TRUE(cell()); | |
180 EXPECT_TRUE(gps()); | |
181 EXPECT_TRUE(cell()->has_listeners()); | |
182 EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_); | |
183 EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_); | |
184 EXPECT_FALSE(observer_->last_position_.Validate()); | |
185 EXPECT_EQ(Geoposition::ERROR_CODE_NONE, | |
186 observer_->last_position_.error_code); | |
187 | |
188 SetReferencePosition(cell()); | |
189 | |
190 EXPECT_TRUE(observer_->last_position_.Validate() || | |
191 observer_->last_position_.error_code != | |
192 Geoposition::ERROR_CODE_NONE); | |
193 EXPECT_EQ(cell()->position_.latitude, | |
194 observer_->last_position_.latitude); | |
195 | |
196 EXPECT_FALSE(cell()->is_permission_granted_); | |
197 EXPECT_FALSE(arbitrator_->HasPermissionBeenGranted()); | |
198 arbitrator_->OnPermissionGranted(); | |
199 EXPECT_TRUE(arbitrator_->HasPermissionBeenGranted()); | |
200 EXPECT_TRUE(cell()->is_permission_granted_); | |
201 } | |
202 | |
203 TEST_F(GeolocationLocationArbitratorTest, SetObserverOptions) { | |
204 arbitrator_->StartProviders(GeolocationObserverOptions(false)); | |
205 access_token_store_->NotifyDelegateTokensLoaded(); | |
206 ASSERT_TRUE(cell()); | |
207 ASSERT_TRUE(gps()); | |
208 EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_); | |
209 EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_); | |
210 SetReferencePosition(cell()); | |
211 EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, cell()->state_); | |
212 EXPECT_EQ(MockLocationProvider::LOW_ACCURACY, gps()->state_); | |
213 arbitrator_->StartProviders(GeolocationObserverOptions(true)); | |
214 EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, cell()->state_); | |
215 EXPECT_EQ(MockLocationProvider::HIGH_ACCURACY, gps()->state_); | |
216 } | |
217 | |
218 TEST_F(GeolocationLocationArbitratorTest, Arbitration) { | |
219 arbitrator_->StartProviders(GeolocationObserverOptions(false)); | |
220 access_token_store_->NotifyDelegateTokensLoaded(); | |
221 ASSERT_TRUE(cell()); | |
222 ASSERT_TRUE(gps()); | |
223 | |
224 SetPositionFix(cell(), 1, 2, 150); | |
225 | |
226 // First position available | |
227 EXPECT_TRUE(observer_->last_position_.Validate()); | |
228 CheckLastPositionInfo(1, 2, 150); | |
229 | |
230 SetPositionFix(gps(), 3, 4, 50); | |
231 | |
232 // More accurate fix available | |
233 CheckLastPositionInfo(3, 4, 50); | |
234 | |
235 SetPositionFix(cell(), 5, 6, 150); | |
236 | |
237 // New fix is available but it's less accurate, older fix should be kept. | |
238 CheckLastPositionInfo(3, 4, 50); | |
239 | |
240 // Advance time, and notify once again | |
241 AdvanceTimeNow(SwitchOnFreshnessCliff()); | |
242 cell()->HandlePositionChanged(cell()->position_); | |
243 | |
244 // New fix is available, less accurate but fresher | |
245 CheckLastPositionInfo(5, 6, 150); | |
246 | |
247 // Advance time, and set a low accuracy position | |
248 AdvanceTimeNow(SwitchOnFreshnessCliff()); | |
249 SetPositionFix(cell(), 5.676731, 139.629385, 1000); | |
250 CheckLastPositionInfo(5.676731, 139.629385, 1000); | |
251 | |
252 // 15 secs later, step outside. Switches to gps signal. | |
253 AdvanceTimeNow(base::TimeDelta::FromSeconds(15)); | |
254 SetPositionFix(gps(), 3.5676457, 139.629198, 50); | |
255 CheckLastPositionInfo(3.5676457, 139.629198, 50); | |
256 | |
257 // 5 mins later switch cells while walking. Stay on gps. | |
258 AdvanceTimeNow(base::TimeDelta::FromMinutes(5)); | |
259 SetPositionFix(cell(), 3.567832, 139.634648, 300); | |
260 SetPositionFix(gps(), 3.5677675, 139.632314, 50); | |
261 CheckLastPositionInfo(3.5677675, 139.632314, 50); | |
262 | |
263 // Ride train and gps signal degrades slightly. Stay on fresher gps | |
264 AdvanceTimeNow(base::TimeDelta::FromMinutes(5)); | |
265 SetPositionFix(gps(), 3.5679026, 139.634777, 300); | |
266 CheckLastPositionInfo(3.5679026, 139.634777, 300); | |
267 | |
268 // 14 minutes later | |
269 AdvanceTimeNow(base::TimeDelta::FromMinutes(14)); | |
270 | |
271 // GPS reading misses a beat, but don't switch to cell yet to avoid | |
272 // oscillating. | |
273 SetPositionFix(gps(), 3.5659005, 139.682579, 300); | |
274 | |
275 AdvanceTimeNow(base::TimeDelta::FromSeconds(7)); | |
276 SetPositionFix(cell(), 3.5689579, 139.691420, 1000); | |
277 CheckLastPositionInfo(3.5659005, 139.682579, 300); | |
278 | |
279 // 1 minute later | |
280 AdvanceTimeNow(base::TimeDelta::FromMinutes(1)); | |
281 | |
282 // Enter tunnel. Stay on fresher gps for a moment. | |
283 SetPositionFix(cell(), 3.5657078, 139.68922, 300); | |
284 SetPositionFix(gps(), 3.5657104, 139.690341, 300); | |
285 CheckLastPositionInfo(3.5657104, 139.690341, 300); | |
286 | |
287 // 2 minutes later | |
288 AdvanceTimeNow(base::TimeDelta::FromMinutes(2)); | |
289 // Arrive in station. Cell moves but GPS is stale. Switch to fresher cell. | |
290 SetPositionFix(cell(), 3.5658700, 139.069979, 1000); | |
291 CheckLastPositionInfo(3.5658700, 139.069979, 1000); | |
292 } | |
293 | |
294 } // namespace content | |
OLD | NEW |