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 <map> 6 #include <queue> 7 8 #include "base/message_loop/message_loop.h" 9 #include "base/synchronization/lock.h" 10 #include "content/browser/device_orientation/data_fetcher.h" 11 #include "content/browser/device_orientation/device_data.h" 12 #include "content/browser/device_orientation/orientation.h" 13 #include "content/browser/device_orientation/provider.h" 14 #include "content/browser/device_orientation/provider_impl.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 namespace content { 18 namespace { 19 20 // Class for testing multiple types of device data. 21 class TestData : public DeviceData { 22 public: 23 TestData() 24 : value_(0) { 25 } 26 27 // From DeviceData. 28 virtual IPC::Message* CreateIPCMessage(int render_view_id) const OVERRIDE { 29 NOTREACHED(); 30 return NULL; 31 } 32 virtual bool ShouldFireEvent(const DeviceData* old_data) const OVERRIDE { 33 return true; 34 } 35 36 void set_value(double value) { value_ = value; } 37 double value() const { return value_; } 38 39 private: 40 virtual ~TestData() { } 41 42 double value_; 43 }; 44 45 // Class for checking expectations on device_data updates from the Provider. 46 class UpdateChecker : public Provider::Observer { 47 public: 48 UpdateChecker(DeviceData::Type device_data_type, 49 int *expectations_count_ptr) 50 : Observer(device_data_type), 51 expectations_count_ptr_(expectations_count_ptr) { 52 } 53 virtual ~UpdateChecker() {} 54 55 // From Provider::Observer. 56 virtual void OnDeviceDataUpdate(const DeviceData* device_data, 57 DeviceData::Type device_data_type) OVERRIDE = 0; 58 59 void AddExpectation(const DeviceData* device_data) { 60 scoped_refptr<const DeviceData> expected_device_data(device_data); 61 expectations_queue_.push(expected_device_data); 62 ++(*expectations_count_ptr_); 63 } 64 65 protected: 66 // Set up by the test fixture, which then blocks while it is accessed 67 // from OnDeviceDataUpdate which is executed on the test fixture's 68 // message_loop_. 69 int* expectations_count_ptr_; 70 std::queue<scoped_refptr<const DeviceData> > expectations_queue_; 71 }; 72 73 // Class for checking expectations on orientation updates from the Provider. 74 class OrientationUpdateChecker : public UpdateChecker { 75 public: 76 explicit OrientationUpdateChecker(int* expectations_count_ptr) 77 : UpdateChecker(DeviceData::kTypeOrientation, expectations_count_ptr) { 78 } 79 80 virtual ~OrientationUpdateChecker() {} 81 82 // From UpdateChecker. 83 virtual void OnDeviceDataUpdate(const DeviceData* device_data, 84 DeviceData::Type device_data_type) OVERRIDE { 85 ASSERT_FALSE(expectations_queue_.empty()); 86 ASSERT_EQ(DeviceData::kTypeOrientation, device_data_type); 87 88 scoped_refptr<const Orientation> orientation( 89 static_cast<const Orientation*>(device_data)); 90 if (orientation.get() == NULL) 91 orientation = new Orientation(); 92 93 scoped_refptr<const Orientation> expected(static_cast<const Orientation*>( 94 (expectations_queue_.front().get()))); 95 expectations_queue_.pop(); 96 97 EXPECT_EQ(expected->can_provide_alpha(), orientation->can_provide_alpha()); 98 EXPECT_EQ(expected->can_provide_beta(), orientation->can_provide_beta()); 99 EXPECT_EQ(expected->can_provide_gamma(), orientation->can_provide_gamma()); 100 EXPECT_EQ(expected->can_provide_absolute(), 101 orientation->can_provide_absolute()); 102 if (expected->can_provide_alpha()) 103 EXPECT_EQ(expected->alpha(), orientation->alpha()); 104 if (expected->can_provide_beta()) 105 EXPECT_EQ(expected->beta(), orientation->beta()); 106 if (expected->can_provide_gamma()) 107 EXPECT_EQ(expected->gamma(), orientation->gamma()); 108 if (expected->can_provide_absolute()) 109 EXPECT_EQ(expected->absolute(), orientation->absolute()); 110 111 --(*expectations_count_ptr_); 112 113 if (*expectations_count_ptr_ == 0) { 114 base::MessageLoop::current()->PostTask(FROM_HERE, 115 base::MessageLoop::QuitClosure()); 116 } 117 } 118 }; 119 120 // Class for checking expectations on test_data updates from the Provider. 121 class TestDataUpdateChecker : public UpdateChecker { 122 public: 123 explicit TestDataUpdateChecker(int* expectations_count_ptr) 124 : UpdateChecker(DeviceData::kTypeTest, expectations_count_ptr) { 125 } 126 127 // From UpdateChecker. 128 virtual void OnDeviceDataUpdate(const DeviceData* device_data, 129 DeviceData::Type device_data_type) OVERRIDE { 130 ASSERT_FALSE(expectations_queue_.empty()); 131 ASSERT_EQ(DeviceData::kTypeTest, device_data_type); 132 133 scoped_refptr<const TestData> test_data( 134 static_cast<const TestData*>(device_data)); 135 if (test_data.get() == NULL) 136 test_data = new TestData(); 137 138 scoped_refptr<const TestData> expected(static_cast<const TestData*>( 139 (expectations_queue_.front().get()))); 140 expectations_queue_.pop(); 141 142 EXPECT_EQ(expected->value(), test_data->value()); 143 144 --(*expectations_count_ptr_); 145 146 if (*expectations_count_ptr_ == 0) { 147 base::MessageLoop::current()->PostTask(FROM_HERE, 148 base::MessageLoop::QuitClosure()); 149 } 150 } 151 }; 152 153 // Class for injecting test device data into the Provider. 154 class MockDeviceDataFactory 155 : public base::RefCountedThreadSafe<MockDeviceDataFactory> { 156 public: 157 MockDeviceDataFactory() 158 : is_failing_(false) { 159 } 160 161 static void SetCurInstance(MockDeviceDataFactory* instance) { 162 if (instance) { 163 EXPECT_FALSE(instance_); 164 } 165 else { 166 EXPECT_TRUE(instance_); 167 } 168 instance_ = instance; 169 } 170 171 static DataFetcher* CreateDataFetcher() { 172 EXPECT_TRUE(instance_); 173 return new MockDataFetcher(instance_); 174 } 175 176 void SetDeviceData(const DeviceData* device_data, DeviceData::Type type) { 177 base::AutoLock auto_lock(lock_); 178 device_data_map_[type] = device_data; 179 } 180 181 void SetFailing(bool is_failing) { 182 base::AutoLock auto_lock(lock_); 183 is_failing_ = is_failing; 184 } 185 186 private: 187 friend class base::RefCountedThreadSafe<MockDeviceDataFactory>; 188 189 ~MockDeviceDataFactory() { 190 } 191 192 // Owned by ProviderImpl. Holds a reference back to MockDeviceDataFactory. 193 class MockDataFetcher : public DataFetcher { 194 public: 195 explicit MockDataFetcher(MockDeviceDataFactory* device_data_factory) 196 : device_data_factory_(device_data_factory) { } 197 198 // From DataFetcher. Called by the Provider. 199 virtual const DeviceData* GetDeviceData( 200 DeviceData::Type device_data_type) OVERRIDE { 201 base::AutoLock auto_lock(device_data_factory_->lock_); 202 if (device_data_factory_->is_failing_) 203 return NULL; 204 return device_data_factory_->device_data_map_[device_data_type].get(); 205 } 206 207 private: 208 scoped_refptr<MockDeviceDataFactory> device_data_factory_; 209 }; 210 211 static MockDeviceDataFactory* instance_; 212 std::map<DeviceData::Type, scoped_refptr<const DeviceData> > device_data_map_; 213 bool is_failing_; 214 base::Lock lock_; 215 }; 216 217 MockDeviceDataFactory* MockDeviceDataFactory::instance_; 218 219 class DeviceOrientationProviderTest : public testing::Test { 220 public: 221 DeviceOrientationProviderTest() 222 : pending_expectations_(0) { 223 } 224 225 virtual void TearDown() { 226 provider_ = NULL; 227 228 // Make sure it is really gone. 229 EXPECT_FALSE(Provider::GetInstanceForTests()); 230 231 // Clean up in any case, so as to not break subsequent test. 232 Provider::SetInstanceForTests(NULL); 233 } 234 235 // Initialize the test fixture with a ProviderImpl that uses the 236 // DataFetcherFactory factory. 237 void Init(ProviderImpl::DataFetcherFactory factory) { 238 provider_ = new ProviderImpl(factory); 239 Provider::SetInstanceForTests(provider_.get()); 240 } 241 242 protected: 243 // Number of pending expectations. 244 int pending_expectations_; 245 246 // Provider instance under test. 247 scoped_refptr<Provider> provider_; 248 249 // Message loop for the test thread. 250 base::MessageLoop message_loop_; 251 }; 252 253 TEST_F(DeviceOrientationProviderTest, FailingTest) { 254 scoped_refptr<MockDeviceDataFactory> device_data_factory( 255 new MockDeviceDataFactory()); 256 MockDeviceDataFactory::SetCurInstance(device_data_factory.get()); 257 Init(MockDeviceDataFactory::CreateDataFetcher); 258 259 scoped_ptr<OrientationUpdateChecker> checker_a( 260 new OrientationUpdateChecker(&pending_expectations_)); 261 scoped_ptr<OrientationUpdateChecker> checker_b( 262 new OrientationUpdateChecker(&pending_expectations_)); 263 264 checker_a->AddExpectation(new Orientation()); 265 provider_->AddObserver(checker_a.get()); 266 base::MessageLoop::current()->Run(); 267 268 checker_b->AddExpectation(new Orientation()); 269 provider_->AddObserver(checker_b.get()); 270 base::MessageLoop::current()->Run(); 271 272 MockDeviceDataFactory::SetCurInstance(NULL); 273 } 274 275 TEST_F(DeviceOrientationProviderTest, ProviderIsSingleton) { 276 scoped_refptr<MockDeviceDataFactory> device_data_factory( 277 new MockDeviceDataFactory()); 278 MockDeviceDataFactory::SetCurInstance(device_data_factory.get()); 279 Init(MockDeviceDataFactory::CreateDataFetcher); 280 281 scoped_refptr<Provider> provider_a(Provider::GetInstance()); 282 scoped_refptr<Provider> provider_b(Provider::GetInstance()); 283 284 EXPECT_EQ(provider_a.get(), provider_b.get()); 285 MockDeviceDataFactory::SetCurInstance(NULL); 286 } 287 288 TEST_F(DeviceOrientationProviderTest, BasicPushTest) { 289 scoped_refptr<MockDeviceDataFactory> device_data_factory( 290 new MockDeviceDataFactory()); 291 MockDeviceDataFactory::SetCurInstance(device_data_factory.get()); 292 Init(MockDeviceDataFactory::CreateDataFetcher); 293 scoped_refptr<Orientation> test_orientation(new Orientation()); 294 test_orientation->set_alpha(1); 295 test_orientation->set_beta(2); 296 test_orientation->set_gamma(3); 297 test_orientation->set_absolute(true); 298 299 scoped_ptr<OrientationUpdateChecker> checker( 300 new OrientationUpdateChecker(&pending_expectations_)); 301 checker->AddExpectation(test_orientation.get()); 302 device_data_factory->SetDeviceData(test_orientation.get(), 303 DeviceData::kTypeOrientation); 304 provider_->AddObserver(checker.get()); 305 base::MessageLoop::current()->Run(); 306 307 provider_->RemoveObserver(checker.get()); 308 MockDeviceDataFactory::SetCurInstance(NULL); 309 } 310 311 // Tests multiple observers observing the same type of data. 312 TEST_F(DeviceOrientationProviderTest, MultipleObserversPushTest) { 313 scoped_refptr<MockDeviceDataFactory> device_data_factory( 314 new MockDeviceDataFactory()); 315 MockDeviceDataFactory::SetCurInstance(device_data_factory.get()); 316 Init(MockDeviceDataFactory::CreateDataFetcher); 317 318 scoped_refptr<Orientation> test_orientations[] = {new Orientation(), 319 new Orientation(), new Orientation()}; 320 test_orientations[0]->set_alpha(1); 321 test_orientations[0]->set_beta(2); 322 test_orientations[0]->set_gamma(3); 323 test_orientations[0]->set_absolute(true); 324 325 test_orientations[1]->set_alpha(4); 326 test_orientations[1]->set_beta(5); 327 test_orientations[1]->set_gamma(6); 328 test_orientations[1]->set_absolute(false); 329 330 test_orientations[2]->set_alpha(7); 331 test_orientations[2]->set_beta(8); 332 test_orientations[2]->set_gamma(9); 333 // can't provide absolute 334 335 scoped_ptr<OrientationUpdateChecker> checker_a( 336 new OrientationUpdateChecker(&pending_expectations_)); 337 scoped_ptr<OrientationUpdateChecker> checker_b( 338 new OrientationUpdateChecker(&pending_expectations_)); 339 scoped_ptr<OrientationUpdateChecker> checker_c( 340 new OrientationUpdateChecker(&pending_expectations_)); 341 342 checker_a->AddExpectation(test_orientations[0].get()); 343 device_data_factory->SetDeviceData(test_orientations[0].get(), 344 DeviceData::kTypeOrientation); 345 provider_->AddObserver(checker_a.get()); 346 base::MessageLoop::current()->Run(); 347 348 checker_a->AddExpectation(test_orientations[1].get()); 349 checker_b->AddExpectation(test_orientations[0].get()); 350 checker_b->AddExpectation(test_orientations[1].get()); 351 device_data_factory->SetDeviceData(test_orientations[1].get(), 352 DeviceData::kTypeOrientation); 353 provider_->AddObserver(checker_b.get()); 354 base::MessageLoop::current()->Run(); 355 356 provider_->RemoveObserver(checker_a.get()); 357 checker_b->AddExpectation(test_orientations[2].get()); 358 checker_c->AddExpectation(test_orientations[1].get()); 359 checker_c->AddExpectation(test_orientations[2].get()); 360 device_data_factory->SetDeviceData(test_orientations[2].get(), 361 DeviceData::kTypeOrientation); 362 provider_->AddObserver(checker_c.get()); 363 base::MessageLoop::current()->Run(); 364 365 provider_->RemoveObserver(checker_b.get()); 366 provider_->RemoveObserver(checker_c.get()); 367 MockDeviceDataFactory::SetCurInstance(NULL); 368 } 369 370 // Test for when the fetcher cannot provide the first type of data but can 371 // provide the second type. 372 TEST_F(DeviceOrientationProviderTest, FailingFirstDataTypeTest) { 373 374 scoped_refptr<MockDeviceDataFactory> device_data_factory( 375 new MockDeviceDataFactory()); 376 MockDeviceDataFactory::SetCurInstance(device_data_factory.get()); 377 Init(MockDeviceDataFactory::CreateDataFetcher); 378 379 scoped_ptr<TestDataUpdateChecker> test_data_checker( 380 new TestDataUpdateChecker(&pending_expectations_)); 381 scoped_ptr<OrientationUpdateChecker> orientation_checker( 382 new OrientationUpdateChecker(&pending_expectations_)); 383 384 scoped_refptr<Orientation> test_orientation(new Orientation()); 385 test_orientation->set_alpha(1); 386 test_orientation->set_beta(2); 387 test_orientation->set_gamma(3); 388 test_orientation->set_absolute(true); 389 390 test_data_checker->AddExpectation(new TestData()); 391 provider_->AddObserver(test_data_checker.get()); 392 base::MessageLoop::current()->Run(); 393 394 orientation_checker->AddExpectation(test_orientation.get()); 395 device_data_factory->SetDeviceData(test_orientation.get(), 396 DeviceData::kTypeOrientation); 397 provider_->AddObserver(orientation_checker.get()); 398 base::MessageLoop::current()->Run(); 399 400 provider_->RemoveObserver(test_data_checker.get()); 401 provider_->RemoveObserver(orientation_checker.get()); 402 MockDeviceDataFactory::SetCurInstance(NULL); 403 } 404 405 #if defined(OS_LINUX) || defined(OS_WIN) 406 // Flakily DCHECKs on Linux. See crbug.com/104950. 407 // FLAKY on Win. See crbug.com/104950. 408 #define MAYBE_ObserverNotRemoved DISABLED_ObserverNotRemoved 409 #else 410 #define MAYBE_ObserverNotRemoved ObserverNotRemoved 411 #endif 412 TEST_F(DeviceOrientationProviderTest, MAYBE_ObserverNotRemoved) { 413 scoped_refptr<MockDeviceDataFactory> device_data_factory( 414 new MockDeviceDataFactory()); 415 MockDeviceDataFactory::SetCurInstance(device_data_factory.get()); 416 Init(MockDeviceDataFactory::CreateDataFetcher); 417 scoped_refptr<Orientation> test_orientation(new Orientation()); 418 test_orientation->set_alpha(1); 419 test_orientation->set_beta(2); 420 test_orientation->set_gamma(3); 421 test_orientation->set_absolute(true); 422 423 scoped_refptr<Orientation> test_orientation2(new Orientation()); 424 test_orientation2->set_alpha(4); 425 test_orientation2->set_beta(5); 426 test_orientation2->set_gamma(6); 427 test_orientation2->set_absolute(false); 428 429 scoped_ptr<OrientationUpdateChecker> checker( 430 new OrientationUpdateChecker(&pending_expectations_)); 431 checker->AddExpectation(test_orientation.get()); 432 device_data_factory->SetDeviceData(test_orientation.get(), 433 DeviceData::kTypeOrientation); 434 provider_->AddObserver(checker.get()); 435 base::MessageLoop::current()->Run(); 436 437 checker->AddExpectation(test_orientation2.get()); 438 device_data_factory->SetDeviceData(test_orientation2.get(), 439 DeviceData::kTypeOrientation); 440 base::MessageLoop::current()->Run(); 441 442 MockDeviceDataFactory::SetCurInstance(NULL); 443 444 // Note that checker is not removed. This should not be a problem. 445 } 446 447 #if defined(OS_WIN) 448 // FLAKY on Win. See crbug.com/104950. 449 #define MAYBE_StartFailing DISABLED_StartFailing 450 #else 451 #define MAYBE_StartFailing StartFailing 452 #endif 453 TEST_F(DeviceOrientationProviderTest, MAYBE_StartFailing) { 454 scoped_refptr<MockDeviceDataFactory> device_data_factory( 455 new MockDeviceDataFactory()); 456 MockDeviceDataFactory::SetCurInstance(device_data_factory.get()); 457 Init(MockDeviceDataFactory::CreateDataFetcher); 458 scoped_refptr<Orientation> test_orientation(new Orientation()); 459 test_orientation->set_alpha(1); 460 test_orientation->set_beta(2); 461 test_orientation->set_gamma(3); 462 test_orientation->set_absolute(true); 463 464 scoped_ptr<OrientationUpdateChecker> checker_a(new OrientationUpdateChecker( 465 &pending_expectations_)); 466 scoped_ptr<OrientationUpdateChecker> checker_b(new OrientationUpdateChecker( 467 &pending_expectations_)); 468 469 device_data_factory->SetDeviceData(test_orientation.get(), 470 DeviceData::kTypeOrientation); 471 checker_a->AddExpectation(test_orientation.get()); 472 provider_->AddObserver(checker_a.get()); 473 base::MessageLoop::current()->Run(); 474 475 checker_a->AddExpectation(new Orientation()); 476 device_data_factory->SetFailing(true); 477 base::MessageLoop::current()->Run(); 478 479 checker_b->AddExpectation(new Orientation()); 480 provider_->AddObserver(checker_b.get()); 481 base::MessageLoop::current()->Run(); 482 483 provider_->RemoveObserver(checker_a.get()); 484 provider_->RemoveObserver(checker_b.get()); 485 MockDeviceDataFactory::SetCurInstance(NULL); 486 } 487 488 TEST_F(DeviceOrientationProviderTest, StartStopStart) { 489 scoped_refptr<MockDeviceDataFactory> device_data_factory( 490 new MockDeviceDataFactory()); 491 MockDeviceDataFactory::SetCurInstance(device_data_factory.get()); 492 Init(MockDeviceDataFactory::CreateDataFetcher); 493 494 scoped_refptr<Orientation> test_orientation(new Orientation()); 495 test_orientation->set_alpha(1); 496 test_orientation->set_beta(2); 497 test_orientation->set_gamma(3); 498 test_orientation->set_absolute(true); 499 500 scoped_refptr<Orientation> test_orientation2(new Orientation()); 501 test_orientation2->set_alpha(4); 502 test_orientation2->set_beta(5); 503 test_orientation2->set_gamma(6); 504 test_orientation2->set_absolute(false); 505 506 scoped_ptr<OrientationUpdateChecker> checker_a(new OrientationUpdateChecker( 507 &pending_expectations_)); 508 scoped_ptr<OrientationUpdateChecker> checker_b(new OrientationUpdateChecker( 509 &pending_expectations_)); 510 511 checker_a->AddExpectation(test_orientation.get()); 512 device_data_factory->SetDeviceData(test_orientation.get(), 513 DeviceData::kTypeOrientation); 514 provider_->AddObserver(checker_a.get()); 515 base::MessageLoop::current()->Run(); 516 517 provider_->RemoveObserver(checker_a.get()); // This stops the Provider. 518 519 checker_b->AddExpectation(test_orientation2.get()); 520 device_data_factory->SetDeviceData(test_orientation2.get(), 521 DeviceData::kTypeOrientation); 522 provider_->AddObserver(checker_b.get()); 523 base::MessageLoop::current()->Run(); 524 525 provider_->RemoveObserver(checker_b.get()); 526 MockDeviceDataFactory::SetCurInstance(NULL); 527 } 528 529 // Tests that Orientation events only fire if the change is significant. 530 TEST_F(DeviceOrientationProviderTest, OrientationSignificantlyDifferent) { 531 scoped_refptr<MockDeviceDataFactory> device_data_factory( 532 new MockDeviceDataFactory()); 533 MockDeviceDataFactory::SetCurInstance(device_data_factory.get()); 534 Init(MockDeviceDataFactory::CreateDataFetcher); 535 536 // Values that should be well below or above the implementation's 537 // significane threshold. 538 const double kInsignificantDifference = 1e-6; 539 const double kSignificantDifference = 30; 540 const double kAlpha = 4, kBeta = 5, kGamma = 6; 541 542 scoped_refptr<Orientation> first_orientation(new Orientation()); 543 first_orientation->set_alpha(kAlpha); 544 first_orientation->set_beta(kBeta); 545 first_orientation->set_gamma(kGamma); 546 first_orientation->set_absolute(true); 547 548 scoped_refptr<Orientation> second_orientation(new Orientation()); 549 second_orientation->set_alpha(kAlpha + kInsignificantDifference); 550 second_orientation->set_beta(kBeta + kInsignificantDifference); 551 second_orientation->set_gamma(kGamma + kInsignificantDifference); 552 second_orientation->set_absolute(false); 553 554 scoped_refptr<Orientation> third_orientation(new Orientation()); 555 third_orientation->set_alpha(kAlpha + kSignificantDifference); 556 third_orientation->set_beta(kBeta + kSignificantDifference); 557 third_orientation->set_gamma(kGamma + kSignificantDifference); 558 // can't provide absolute 559 560 scoped_ptr<OrientationUpdateChecker> checker_a(new OrientationUpdateChecker( 561 &pending_expectations_)); 562 scoped_ptr<OrientationUpdateChecker> checker_b(new OrientationUpdateChecker( 563 &pending_expectations_)); 564 565 device_data_factory->SetDeviceData(first_orientation.get(), 566 DeviceData::kTypeOrientation); 567 checker_a->AddExpectation(first_orientation.get()); 568 provider_->AddObserver(checker_a.get()); 569 base::MessageLoop::current()->Run(); 570 571 // The observers should not see this insignificantly different orientation. 572 device_data_factory->SetDeviceData(second_orientation.get(), 573 DeviceData::kTypeOrientation); 574 checker_b->AddExpectation(first_orientation.get()); 575 provider_->AddObserver(checker_b.get()); 576 base::MessageLoop::current()->Run(); 577 578 device_data_factory->SetDeviceData(third_orientation.get(), 579 DeviceData::kTypeOrientation); 580 checker_a->AddExpectation(third_orientation.get()); 581 checker_b->AddExpectation(third_orientation.get()); 582 base::MessageLoop::current()->Run(); 583 584 provider_->RemoveObserver(checker_a.get()); 585 provider_->RemoveObserver(checker_b.get()); 586 MockDeviceDataFactory::SetCurInstance(NULL); 587 } 588 589 } // namespace 590 591 } // namespace content 592