Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / geofencing / geofencing_manager_unittest.cc
blob16cf1bbe895ef89ce2f1d732090e9e3c778d5582
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/callback.h"
6 #include "base/message_loop/message_loop.h"
7 #include "content/browser/geofencing/geofencing_manager.h"
8 #include "content/browser/geofencing/geofencing_service.h"
9 #include "content/browser/service_worker/embedded_worker_test_helper.h"
10 #include "content/browser/service_worker/service_worker_context_wrapper.h"
11 #include "content/public/test/test_browser_thread_bundle.h"
12 #include "content/public/test/test_utils.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
17 using blink::WebCircularGeofencingRegion;
18 typedef std::map<std::string, WebCircularGeofencingRegion> RegionMap;
20 namespace {
22 static const int kRenderProcessId = 99;
23 static const char* kTestRegionId = "region-id";
24 static const int64 kTestGeofencingRegistrationId = 42;
25 static const int64 kTestGeofencingRegistrationId2 = 43;
27 bool RegionsMatch(const WebCircularGeofencingRegion& expected,
28 const WebCircularGeofencingRegion& arg) {
29 return testing::Matches(expected.latitude)(arg.latitude) &&
30 testing::Matches(expected.longitude)(arg.longitude) &&
31 testing::Matches(expected.radius)(arg.radius);
35 namespace content {
37 class TestGeofencingService : public GeofencingService {
38 public:
39 TestGeofencingService() : is_available_(false) {}
41 bool IsServiceAvailable() override { return is_available_; }
43 void SetIsServiceAvailable(bool is_available) {
44 is_available_ = is_available;
47 MOCK_METHOD2(RegisterRegion,
48 int64(const WebCircularGeofencingRegion& region,
49 GeofencingRegistrationDelegate* delegate));
50 MOCK_METHOD1(UnregisterRegion, void(int64 geofencing_registration_id));
52 private:
53 bool is_available_;
56 ACTION_P(SaveDelegate, delegate) {
57 *delegate = arg1;
60 ACTION_P(QuitRunner, runner) {
61 runner->Quit();
64 MATCHER_P(WebCircularGeofencingRegionEq, expected, "") {
65 return RegionsMatch(expected, arg);
68 class StatusCatcher {
69 public:
70 StatusCatcher() : was_called_(false), runner_(new MessageLoopRunner()) {}
72 void Done(GeofencingStatus status) {
73 CHECK(!was_called_);
74 result_ = status;
75 was_called_ = true;
76 runner_->Quit();
79 GeofencingStatus Wait() {
80 runner_->Run();
81 CHECK(was_called_);
82 return result_;
85 private:
86 bool was_called_;
87 GeofencingStatus result_;
88 scoped_refptr<MessageLoopRunner> runner_;
91 void SaveResponseCallback(bool* called,
92 int64* store_registration_id,
93 ServiceWorkerStatusCode status,
94 const std::string& status_message,
95 int64 registration_id) {
96 EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
97 *called = true;
98 *store_registration_id = registration_id;
101 ServiceWorkerContextCore::RegistrationCallback MakeRegisteredCallback(
102 bool* called,
103 int64* store_registration_id) {
104 return base::Bind(&SaveResponseCallback, called, store_registration_id);
107 void CallCompletedCallback(bool* called, ServiceWorkerStatusCode) {
108 *called = true;
111 ServiceWorkerContextCore::UnregistrationCallback MakeUnregisteredCallback(
112 bool* called) {
113 return base::Bind(&CallCompletedCallback, called);
116 class GeofencingManagerTest : public testing::Test {
117 public:
118 GeofencingManagerTest() : service_(nullptr) {
119 test_region_.latitude = 37.421999;
120 test_region_.longitude = -122.084015;
121 test_region_.radius = 100;
122 expected_regions_[kTestRegionId] = test_region_;
125 void SetUp() override {
126 helper_.reset(
127 new EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId));
128 service_ = new TestGeofencingService();
129 manager_ = new GeofencingManager(helper_->context_wrapper());
130 manager_->SetServiceForTesting(service_);
131 manager_->Init();
133 worker1_ = RegisterServiceWorker("1");
134 worker2_ = RegisterServiceWorker("2");
137 void TearDown() override {
138 worker1_ = nullptr;
139 worker2_ = nullptr;
140 manager_ = nullptr;
141 delete service_;
142 service_ = nullptr;
143 helper_.reset();
146 void SetHasProviderForTests() { service_->SetIsServiceAvailable(true); }
148 scoped_refptr<ServiceWorkerRegistration> RegisterServiceWorker(
149 const std::string& name) {
150 GURL pattern("http://www.example.com/" + name);
151 GURL script_url("http://www.example.com/service_worker.js");
152 int64 registration_id = kInvalidServiceWorkerRegistrationId;
153 bool called = false;
154 helper_->context()->RegisterServiceWorker(
155 pattern, script_url, nullptr,
156 MakeRegisteredCallback(&called, &registration_id));
158 EXPECT_FALSE(called);
159 base::RunLoop().RunUntilIdle();
160 EXPECT_TRUE(called);
161 scoped_refptr<ServiceWorkerRegistration> worker(
162 new ServiceWorkerRegistration(pattern, registration_id,
163 helper_->context()->AsWeakPtr()));
164 // ServiceWorkerRegistration posts a notification task on construction.
165 base::RunLoop().RunUntilIdle();
166 return worker;
169 void UnregisterServiceWorker(
170 const scoped_refptr<ServiceWorkerRegistration>& registration) {
171 bool called = false;
172 helper_->context()->UnregisterServiceWorker(
173 registration->pattern(), MakeUnregisteredCallback(&called));
175 EXPECT_FALSE(called);
176 base::RunLoop().RunUntilIdle();
177 EXPECT_TRUE(called);
180 GeofencingStatus RegisterRegionSync(
181 int64 service_worker_registration_id,
182 const std::string& id,
183 const WebCircularGeofencingRegion& region) {
184 StatusCatcher result;
185 manager_->RegisterRegion(
186 service_worker_registration_id,
188 region,
189 base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
190 return result.Wait();
193 GeofencingStatus RegisterRegionSyncWithServiceResult(
194 int64 service_worker_registration_id,
195 const std::string& id,
196 const WebCircularGeofencingRegion& region,
197 GeofencingStatus service_status,
198 int64 geofencing_registration_id) {
199 StatusCatcher result;
200 GeofencingRegistrationDelegate* delegate = 0;
201 EXPECT_CALL(
202 *service_,
203 RegisterRegion(WebCircularGeofencingRegionEq(region), testing::_))
204 .WillOnce(testing::DoAll(SaveDelegate(&delegate),
205 testing::Return(geofencing_registration_id)));
206 manager_->RegisterRegion(
207 service_worker_registration_id,
209 region,
210 base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
211 CHECK(delegate);
212 delegate->RegistrationFinished(geofencing_registration_id, service_status);
213 return result.Wait();
216 GeofencingStatus UnregisterRegionSync(int64 service_worker_registration_id,
217 const std::string& id,
218 bool should_call_service,
219 int64 geofencing_registration_id = 0) {
220 StatusCatcher result;
221 if (should_call_service) {
222 EXPECT_CALL(*service_, UnregisterRegion(geofencing_registration_id));
224 manager_->UnregisterRegion(
225 service_worker_registration_id,
227 base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
228 return result.Wait();
231 void VerifyRegions(int64 service_worker_registration_id,
232 const RegionMap& expected_regions) {
233 RegionMap regions;
234 EXPECT_EQ(GEOFENCING_STATUS_OK,
235 manager_->GetRegisteredRegions(service_worker_registration_id,
236 &regions));
237 EXPECT_EQ(expected_regions.size(), regions.size());
238 for (RegionMap::const_iterator it = expected_regions.begin();
239 it != expected_regions.end();
240 ++it) {
241 EXPECT_THAT(regions[it->first],
242 WebCircularGeofencingRegionEq(it->second));
246 protected:
247 TestBrowserThreadBundle threads_;
248 scoped_ptr<EmbeddedWorkerTestHelper> helper_;
249 TestGeofencingService* service_;
250 scoped_refptr<GeofencingManager> manager_;
252 WebCircularGeofencingRegion test_region_;
253 RegionMap expected_regions_;
255 scoped_refptr<ServiceWorkerRegistration> worker1_;
256 scoped_refptr<ServiceWorkerRegistration> worker2_;
259 TEST_F(GeofencingManagerTest, RegisterRegion_NoService) {
260 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
261 RegisterRegionSync(worker1_->id(), kTestRegionId, test_region_));
264 TEST_F(GeofencingManagerTest, UnregisterRegion_NoService) {
265 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
266 UnregisterRegionSync(worker1_->id(), kTestRegionId, false));
269 TEST_F(GeofencingManagerTest, GetRegisteredRegions_NoService) {
270 RegionMap regions;
271 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
272 manager_->GetRegisteredRegions(worker1_->id(), &regions));
273 EXPECT_TRUE(regions.empty());
276 TEST_F(GeofencingManagerTest, RegisterRegion_FailsInService) {
277 SetHasProviderForTests();
278 EXPECT_EQ(GEOFENCING_STATUS_ERROR,
279 RegisterRegionSyncWithServiceResult(worker1_->id(), kTestRegionId,
280 test_region_,
281 GEOFENCING_STATUS_ERROR, -1));
284 TEST_F(GeofencingManagerTest, RegisterRegion_SucceedsInService) {
285 SetHasProviderForTests();
286 EXPECT_EQ(GEOFENCING_STATUS_OK,
287 RegisterRegionSyncWithServiceResult(
288 worker1_->id(), kTestRegionId, test_region_,
289 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId));
290 VerifyRegions(worker1_->id(), expected_regions_);
293 TEST_F(GeofencingManagerTest, RegisterRegion_AlreadyRegistered) {
294 SetHasProviderForTests();
295 EXPECT_EQ(GEOFENCING_STATUS_OK,
296 RegisterRegionSyncWithServiceResult(
297 worker1_->id(), kTestRegionId, test_region_,
298 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId));
299 VerifyRegions(worker1_->id(), expected_regions_);
301 WebCircularGeofencingRegion region2;
302 region2.latitude = 43.2;
303 region2.longitude = 1.45;
304 region2.radius = 8.5;
305 EXPECT_EQ(GEOFENCING_STATUS_ERROR,
306 RegisterRegionSync(worker1_->id(), kTestRegionId, region2));
307 VerifyRegions(worker1_->id(), expected_regions_);
310 TEST_F(GeofencingManagerTest, UnregisterRegion_NotRegistered) {
311 SetHasProviderForTests();
312 EXPECT_EQ(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED,
313 UnregisterRegionSync(worker1_->id(), kTestRegionId, false));
316 TEST_F(GeofencingManagerTest, UnregisterRegion_Success) {
317 SetHasProviderForTests();
319 EXPECT_EQ(GEOFENCING_STATUS_OK,
320 RegisterRegionSyncWithServiceResult(
321 worker1_->id(), kTestRegionId, test_region_,
322 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId));
324 EXPECT_EQ(GEOFENCING_STATUS_OK,
325 UnregisterRegionSync(worker1_->id(), kTestRegionId, true,
326 kTestGeofencingRegistrationId));
327 VerifyRegions(worker1_->id(), RegionMap());
330 TEST_F(GeofencingManagerTest, GetRegisteredRegions_RegistrationInProgress) {
331 SetHasProviderForTests();
332 StatusCatcher result;
333 GeofencingRegistrationDelegate* delegate = nullptr;
335 EXPECT_CALL(
336 *service_,
337 RegisterRegion(WebCircularGeofencingRegionEq(test_region_), testing::_))
338 .WillOnce(testing::DoAll(SaveDelegate(&delegate),
339 testing::Return(kTestGeofencingRegistrationId)));
340 manager_->RegisterRegion(
341 worker1_->id(), kTestRegionId, test_region_,
342 base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
344 // At this point the manager should have tried registering the region with
345 // the service, resulting in |delegate| being set. Until the callback is
346 // called the registration is not complete though.
347 EXPECT_NE(delegate, nullptr);
348 VerifyRegions(worker1_->id(), RegionMap());
350 // Now call the callback, and verify the registration completed succesfully.
351 delegate->RegistrationFinished(kTestGeofencingRegistrationId,
352 GEOFENCING_STATUS_OK);
353 EXPECT_EQ(GEOFENCING_STATUS_OK, result.Wait());
354 VerifyRegions(worker1_->id(), expected_regions_);
357 TEST_F(GeofencingManagerTest, UnregisterRegion_RegistrationInProgress) {
358 SetHasProviderForTests();
359 StatusCatcher result;
360 GeofencingRegistrationDelegate* delegate = nullptr;
362 EXPECT_CALL(
363 *service_,
364 RegisterRegion(WebCircularGeofencingRegionEq(test_region_), testing::_))
365 .WillOnce(testing::DoAll(SaveDelegate(&delegate),
366 testing::Return(kTestGeofencingRegistrationId)));
367 manager_->RegisterRegion(
368 worker1_->id(), kTestRegionId, test_region_,
369 base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
371 // At this point the manager should have tried registering the region with
372 // the service, resulting in |delegate| being set. Until the callback is
373 // called the registration is not complete though.
374 EXPECT_NE(delegate, nullptr);
376 EXPECT_EQ(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED,
377 UnregisterRegionSync(worker1_->id(), kTestRegionId, false));
380 TEST_F(GeofencingManagerTest, GetRegisteredRegions_NoRegions) {
381 SetHasProviderForTests();
382 VerifyRegions(worker1_->id(), RegionMap());
385 TEST_F(GeofencingManagerTest, RegisterRegion_SeparateServiceWorkers) {
386 SetHasProviderForTests();
388 EXPECT_EQ(GEOFENCING_STATUS_OK,
389 RegisterRegionSyncWithServiceResult(
390 worker1_->id(), kTestRegionId, test_region_,
391 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId));
393 VerifyRegions(worker1_->id(), expected_regions_);
394 VerifyRegions(worker2_->id(), RegionMap());
396 EXPECT_EQ(GEOFENCING_STATUS_OK,
397 RegisterRegionSyncWithServiceResult(
398 worker2_->id(), kTestRegionId, test_region_,
399 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId2));
401 VerifyRegions(worker1_->id(), expected_regions_);
402 VerifyRegions(worker2_->id(), expected_regions_);
405 TEST_F(GeofencingManagerTest, UnregisterRegion_SeparateServiceWorkers) {
406 SetHasProviderForTests();
408 EXPECT_EQ(GEOFENCING_STATUS_OK,
409 RegisterRegionSyncWithServiceResult(
410 worker1_->id(), kTestRegionId, test_region_,
411 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId));
412 EXPECT_EQ(GEOFENCING_STATUS_OK,
413 RegisterRegionSyncWithServiceResult(
414 worker2_->id(), kTestRegionId, test_region_,
415 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId2));
417 EXPECT_EQ(GEOFENCING_STATUS_OK,
418 UnregisterRegionSync(worker1_->id(), kTestRegionId, true,
419 kTestGeofencingRegistrationId));
421 VerifyRegions(worker1_->id(), RegionMap());
422 VerifyRegions(worker2_->id(), expected_regions_);
424 EXPECT_EQ(GEOFENCING_STATUS_OK,
425 UnregisterRegionSync(worker2_->id(), kTestRegionId, true,
426 kTestGeofencingRegistrationId2));
428 VerifyRegions(worker1_->id(), RegionMap());
429 VerifyRegions(worker2_->id(), RegionMap());
432 TEST_F(GeofencingManagerTest, ShutdownCleansRegistrations) {
433 SetHasProviderForTests();
434 scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner());
435 EXPECT_EQ(GEOFENCING_STATUS_OK,
436 RegisterRegionSyncWithServiceResult(
437 worker1_->id(), kTestRegionId, test_region_,
438 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId));
440 EXPECT_CALL(*service_, UnregisterRegion(kTestGeofencingRegistrationId))
441 .WillOnce(QuitRunner(runner));
442 manager_->Shutdown();
443 runner->Run();
446 TEST_F(GeofencingManagerTest, OnRegistrationDeleted) {
447 SetHasProviderForTests();
449 EXPECT_EQ(GEOFENCING_STATUS_OK,
450 RegisterRegionSyncWithServiceResult(
451 worker1_->id(), kTestRegionId, test_region_,
452 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId));
453 EXPECT_EQ(GEOFENCING_STATUS_OK,
454 RegisterRegionSyncWithServiceResult(
455 worker2_->id(), kTestRegionId, test_region_,
456 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId2));
458 EXPECT_CALL(*service_, UnregisterRegion(kTestGeofencingRegistrationId));
459 UnregisterServiceWorker(worker1_);
460 VerifyRegions(worker1_->id(), RegionMap());
461 VerifyRegions(worker2_->id(), expected_regions_);
463 EXPECT_CALL(*service_, UnregisterRegion(kTestGeofencingRegistrationId2));
464 UnregisterServiceWorker(worker2_);
465 VerifyRegions(worker1_->id(), RegionMap());
466 VerifyRegions(worker2_->id(), RegionMap());
469 TEST_F(GeofencingManagerTest, RegisterRegion_MockedNoService) {
470 manager_->SetMockProvider(GeofencingMockState::SERVICE_UNAVAILABLE);
472 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
473 RegisterRegionSync(worker1_->id(), kTestRegionId, test_region_));
476 TEST_F(GeofencingManagerTest, UnregisterRegion_MockedNoService) {
477 manager_->SetMockProvider(GeofencingMockState::SERVICE_UNAVAILABLE);
479 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
480 UnregisterRegionSync(worker1_->id(), kTestRegionId, false));
483 TEST_F(GeofencingManagerTest, GetRegisteredRegions_MockedNoService) {
484 manager_->SetMockProvider(GeofencingMockState::SERVICE_UNAVAILABLE);
486 RegionMap regions;
487 EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
488 manager_->GetRegisteredRegions(worker1_->id(), &regions));
489 EXPECT_TRUE(regions.empty());
492 TEST_F(GeofencingManagerTest, RegisterRegion_MockedService) {
493 manager_->SetMockProvider(GeofencingMockState::SERVICE_AVAILABLE);
495 // Make sure real service doesn't get called.
496 EXPECT_CALL(*service_, RegisterRegion(testing::_, testing::_)).Times(0);
498 EXPECT_EQ(GEOFENCING_STATUS_OK,
499 RegisterRegionSync(worker1_->id(), kTestRegionId, test_region_));
500 VerifyRegions(worker1_->id(), expected_regions_);
503 TEST_F(GeofencingManagerTest, SetMockProviderClearsRegistrations) {
504 SetHasProviderForTests();
505 EXPECT_EQ(GEOFENCING_STATUS_OK,
506 RegisterRegionSyncWithServiceResult(
507 worker1_->id(), kTestRegionId, test_region_,
508 GEOFENCING_STATUS_OK, kTestGeofencingRegistrationId));
509 VerifyRegions(worker1_->id(), expected_regions_);
511 EXPECT_CALL(*service_, UnregisterRegion(kTestGeofencingRegistrationId));
513 manager_->SetMockProvider(GeofencingMockState::SERVICE_AVAILABLE);
514 VerifyRegions(worker1_->id(), RegionMap());
517 } // namespace content