Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1234)

Unified Diff: chrome/browser/device_orientation/provider_unittest.cc

Issue 3136008: Implement device_orientation::Provider. (Closed)
Patch Set: Patch Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/device_orientation/provider_impl.cc ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/device_orientation/provider_unittest.cc
diff --git a/chrome/browser/device_orientation/provider_unittest.cc b/chrome/browser/device_orientation/provider_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cadc1748fa17d2bcc6f3dd7163f300470b2bcd46
--- /dev/null
+++ b/chrome/browser/device_orientation/provider_unittest.cc
@@ -0,0 +1,369 @@
+// Copyright (c) 2010 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 <queue>
+
+#include "base/lock.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "chrome/browser/device_orientation/data_fetcher.h"
+#include "chrome/browser/device_orientation/orientation.h"
+#include "chrome/browser/device_orientation/provider.h"
+#include "chrome/browser/device_orientation/provider_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device_orientation {
+namespace {
+
+// Class for checking expectations on orientation updates from the Provider.
+class UpdateChecker : public Provider::Observer {
+ public:
+ explicit UpdateChecker(int* expectations_count_ptr)
+ : expectations_count_ptr_(expectations_count_ptr) {
+ }
+
+ // From Provider::Observer.
+ virtual void OnOrientationUpdate(const Orientation& orientation) {
+ ASSERT_FALSE(expectations_queue_.empty());
+
+ Orientation expected = expectations_queue_.front();
+ expectations_queue_.pop();
+
+ EXPECT_EQ(expected.can_provide_alpha_, orientation.can_provide_alpha_);
+ EXPECT_EQ(expected.can_provide_beta_, orientation.can_provide_beta_);
+ EXPECT_EQ(expected.can_provide_gamma_, orientation.can_provide_gamma_);
+ if (expected.can_provide_alpha_)
+ EXPECT_EQ(expected.alpha_, orientation.alpha_);
+ if (expected.can_provide_beta_)
+ EXPECT_EQ(expected.beta_, orientation.beta_);
+ if (expected.can_provide_gamma_)
+ EXPECT_EQ(expected.gamma_, orientation.gamma_);
+
+ --(*expectations_count_ptr_);
+
+ if (*expectations_count_ptr_ == 0) {
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ }
+ }
+
+ void AddExpectation(const Orientation& orientation) {
+ expectations_queue_.push(orientation);
+ ++(*expectations_count_ptr_);
+ }
+
+ private:
+ // Set up by the test fixture, which then blocks while it is accessed
+ // from OnOrientationUpdate which is executed on the test fixture's
+ // message_loop_.
+ int* expectations_count_ptr_;
+ std::queue<Orientation> expectations_queue_;
+};
+
+// Class for injecting test orientation data into the Provider.
+class MockOrientationFactory : public base::RefCounted<MockOrientationFactory> {
+ public:
+ MockOrientationFactory() {
+ EXPECT_FALSE(instance_);
+ instance_ = this;
+ }
+
+ ~MockOrientationFactory() {
+ instance_ = NULL;
+ }
+
+ static DataFetcher* CreateDataFetcher() {
+ EXPECT_TRUE(instance_);
+ return new MockDataFetcher(instance_);
+ }
+
+ void SetOrientation(const Orientation& orientation) {
+ AutoLock auto_lock(lock_);
+ orientation_ = orientation;
+ }
+
+ private:
+ // Owned by ProviderImpl. Holds a reference back to MockOrientationFactory.
+ class MockDataFetcher : public DataFetcher {
+ public:
+ explicit MockDataFetcher(MockOrientationFactory* orientation_factory)
+ : orientation_factory_(orientation_factory) { }
+
+ // From DataFetcher. Called by the Provider.
+ virtual bool GetOrientation(Orientation* orientation) {
+ AutoLock auto_lock(orientation_factory_->lock_);
+ *orientation = orientation_factory_->orientation_;
+ return true;
+ }
+
+ private:
+ scoped_refptr<MockOrientationFactory> orientation_factory_;
+ };
+
+ static MockOrientationFactory* instance_;
+ Orientation orientation_;
+ Lock lock_;
+};
+
+MockOrientationFactory* MockOrientationFactory::instance_;
+
+// Mock DataFetcher that always fails to provide any orientation data.
+class FailingDataFetcher : public DataFetcher {
+ public:
+ // Factory method; passed to and called by the ProviderImpl.
+ static DataFetcher* Create() {
+ return new FailingDataFetcher();
+ }
+
+ // From DataFetcher.
+ virtual bool GetOrientation(Orientation* orientation) {
+ return false;
+ }
+
+ private:
+ FailingDataFetcher() {}
+};
+
+class DeviceOrientationProviderTest : public testing::Test {
+ public:
+ DeviceOrientationProviderTest() {
+ }
+
+ // Initialize the test fixture with a ProviderImpl that uses the
+ // DataFetcherFactories in the null-terminated factories array.
+ void Init(ProviderImpl::DataFetcherFactory* factories) {
+ provider_ = new ProviderImpl(&message_loop_, factories);
+ Provider::SetInstanceForTests(provider_);
+ }
+
+ // Initialize the test fixture with a ProviderImpl that uses the
+ // DataFetcherFactory factory.
+ void Init(ProviderImpl::DataFetcherFactory factory) {
+ ProviderImpl::DataFetcherFactory factories[] = { factory, NULL };
+ Init(factories);
+ }
+
+ void ScheduleAddObserver(Provider::Observer* observer) {
+ Task* task = NewRunnableMethod(provider_.get(), &Provider::AddObserver,
+ observer);
+ message_loop_.PostTask(FROM_HERE, task);
+ }
+
+ void RemoveObserver(Provider::Observer* observer) {
+ Task* task = NewRunnableMethod(provider_.get(), &Provider::RemoveObserver,
+ observer);
+ message_loop_.PostTask(FROM_HERE, task);
+ message_loop_.PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ message_loop_.Run();
+ }
+
+ MessageLoop* message_loop() {
+ return &message_loop_;
+ }
+
+ private:
+ // Provider instance under test.
+ scoped_refptr<Provider> provider_;
+
+ // Message loop for adding or removing observers of the provider, and
+ // receiving orientation updates. In non-test situations, this would
+ // be the message loop of the IO thread.
+ MessageLoop message_loop_;
+};
+
+TEST_F(DeviceOrientationProviderTest, FailingTest) {
+ Init(FailingDataFetcher::Create);
+ int expectations_count = 0;
+
+ scoped_ptr<UpdateChecker> checker_a(new UpdateChecker(&expectations_count));
+ scoped_ptr<UpdateChecker> checker_b(new UpdateChecker(&expectations_count));
+
+ checker_a->AddExpectation(Orientation::Empty());
+ ScheduleAddObserver(checker_a.get());
+ message_loop()->Run();
+
+ checker_b->AddExpectation(Orientation::Empty());
+ ScheduleAddObserver(checker_b.get());
+ message_loop()->Run();
+}
+
+TEST_F(DeviceOrientationProviderTest, ProviderIsSingleton) {
+ Init(FailingDataFetcher::Create);
+
+ scoped_refptr<Provider> provider_a(Provider::GetInstance());
+ scoped_refptr<Provider> provider_b(Provider::GetInstance());
+
+ EXPECT_EQ(provider_a.get(), provider_b.get());
+}
+
+TEST_F(DeviceOrientationProviderTest, BasicPushTest) {
+ scoped_refptr<MockOrientationFactory> orientation_factory(
+ new MockOrientationFactory());
+ Init(MockOrientationFactory::CreateDataFetcher);
+ int expectations_count = 0;
+ const Orientation kTestOrientation(true, 1, true, 2, true, 3);
+
+ scoped_ptr<UpdateChecker> checker(new UpdateChecker(&expectations_count));
+ checker->AddExpectation(kTestOrientation);
+ orientation_factory->SetOrientation(kTestOrientation);
+ ScheduleAddObserver(checker.get());
+ message_loop()->Run();
+
+ RemoveObserver(checker.get());
+}
+
+TEST_F(DeviceOrientationProviderTest, MultipleObserversPushTest) {
+ scoped_refptr<MockOrientationFactory> orientation_factory(
+ new MockOrientationFactory());
+ Init(MockOrientationFactory::CreateDataFetcher);
+ int expectations_count = 0;
+ const Orientation kTestOrientations[] = {
+ Orientation(true, 1, true, 2, true, 3),
+ Orientation(true, 4, true, 5, true, 6),
+ Orientation(true, 7, true, 8, true, 9)};
+
+ scoped_ptr<UpdateChecker> checker_a(new UpdateChecker(&expectations_count));
+ scoped_ptr<UpdateChecker> checker_b(new UpdateChecker(&expectations_count));
+ scoped_ptr<UpdateChecker> checker_c(new UpdateChecker(&expectations_count));
+
+ checker_a->AddExpectation(kTestOrientations[0]);
+ orientation_factory->SetOrientation(kTestOrientations[0]);
+ ScheduleAddObserver(checker_a.get());
+ message_loop()->Run();
+
+ checker_a->AddExpectation(kTestOrientations[1]);
+ checker_b->AddExpectation(kTestOrientations[0]);
+ checker_b->AddExpectation(kTestOrientations[1]);
+ orientation_factory->SetOrientation(kTestOrientations[1]);
+ ScheduleAddObserver(checker_b.get());
+ message_loop()->Run();
+
+ RemoveObserver(checker_a.get());
+ checker_b->AddExpectation(kTestOrientations[2]);
+ checker_c->AddExpectation(kTestOrientations[1]);
+ checker_c->AddExpectation(kTestOrientations[2]);
+ orientation_factory->SetOrientation(kTestOrientations[2]);
+ ScheduleAddObserver(checker_c.get());
+ message_loop()->Run();
+
+ RemoveObserver(checker_b.get());
+ RemoveObserver(checker_c.get());
+}
+
+TEST_F(DeviceOrientationProviderTest, ObserverNotRemoved) {
+ scoped_refptr<MockOrientationFactory> orientation_factory(
+ new MockOrientationFactory());
+ Init(MockOrientationFactory::CreateDataFetcher);
+ int expectations_count = 0;
+ const Orientation kTestOrientation(true, 1, true, 2, true, 3);
+
+ scoped_ptr<UpdateChecker> checker(new UpdateChecker(&expectations_count));
+ checker->AddExpectation(kTestOrientation);
+ orientation_factory->SetOrientation(kTestOrientation);
+ ScheduleAddObserver(checker.get());
+ message_loop()->Run();
+
+ // Note that checker is not removed. This should not be a problem.
+}
+
+TEST_F(DeviceOrientationProviderTest, StartFailing) {
+ scoped_refptr<MockOrientationFactory> orientation_factory(
+ new MockOrientationFactory());
+ Init(MockOrientationFactory::CreateDataFetcher);
+ int expectations_count = 0;
+ const Orientation kTestOrientation(true, 1, true, 2, true, 3);
+
+ scoped_ptr<UpdateChecker> checker_a(new UpdateChecker(&expectations_count));
+ scoped_ptr<UpdateChecker> checker_b(new UpdateChecker(&expectations_count));
+
+ orientation_factory->SetOrientation(kTestOrientation);
+ checker_a->AddExpectation(kTestOrientation);
+ ScheduleAddObserver(checker_a.get());
+ message_loop()->Run();
+
+ checker_a->AddExpectation(Orientation::Empty());
+ orientation_factory->SetOrientation(Orientation::Empty());
+ message_loop()->Run();
+
+ checker_b->AddExpectation(Orientation::Empty());
+ ScheduleAddObserver(checker_b.get());
+ message_loop()->Run();
+
+ RemoveObserver(checker_a.get());
+ RemoveObserver(checker_b.get());
+}
+
+TEST_F(DeviceOrientationProviderTest, StartStopStart) {
+ scoped_refptr<MockOrientationFactory> orientation_factory(
+ new MockOrientationFactory());
+ Init(MockOrientationFactory::CreateDataFetcher);
+ int expectations_count = 0;
+ const Orientation kTestOrientation(true, 1, true, 2, true, 3);
+ const Orientation kTestOrientation2(true, 4, true, 5, true, 6);
+
+ scoped_ptr<UpdateChecker> checker_a(new UpdateChecker(&expectations_count));
+ scoped_ptr<UpdateChecker> checker_b(new UpdateChecker(&expectations_count));
+
+ checker_a->AddExpectation(kTestOrientation);
+ orientation_factory->SetOrientation(kTestOrientation);
+ ScheduleAddObserver(checker_a.get());
+ message_loop()->Run();
+
+ RemoveObserver(checker_a.get()); // This stops the Provider.
+
+ checker_b->AddExpectation(kTestOrientation2);
+ orientation_factory->SetOrientation(kTestOrientation2);
+ ScheduleAddObserver(checker_b.get());
+ message_loop()->Run();
+ RemoveObserver(checker_b.get());
+}
+
+TEST_F(DeviceOrientationProviderTest, SignificantlyDifferent) {
+ scoped_refptr<MockOrientationFactory> orientation_factory(
+ new MockOrientationFactory());
+ Init(MockOrientationFactory::CreateDataFetcher);
+ int expectations_count = 0;
+
+ // Values that should be well below or above the implementation's
+ // significane threshold.
+ const double kInsignificantDifference = 1e-6;
+ const double kSignificantDifference = 30;
+ const double kAlpha = 4, kBeta = 5, kGamma = 6;
+
+ const Orientation first_orientation(true, kAlpha, true, kBeta, true, kGamma);
+
+ const Orientation second_orientation(true, kAlpha + kInsignificantDifference,
+ true, kBeta + kInsignificantDifference,
+ true, kGamma + kInsignificantDifference);
+
+ const Orientation third_orientation(true, kAlpha + kSignificantDifference,
+ true, kBeta + kSignificantDifference,
+ true, kGamma + kSignificantDifference);
+
+ scoped_ptr<UpdateChecker> checker_a(new UpdateChecker(&expectations_count));
+ scoped_ptr<UpdateChecker> checker_b(new UpdateChecker(&expectations_count));
+
+
+ orientation_factory->SetOrientation(first_orientation);
+ checker_a->AddExpectation(first_orientation);
+ ScheduleAddObserver(checker_a.get());
+ message_loop()->Run();
+
+ // The observers should not see this insignificantly different orientation.
+ orientation_factory->SetOrientation(second_orientation);
+ checker_b->AddExpectation(first_orientation);
+ ScheduleAddObserver(checker_b.get());
+ message_loop()->Run();
+
+ orientation_factory->SetOrientation(third_orientation);
+ checker_a->AddExpectation(third_orientation);
+ checker_b->AddExpectation(third_orientation);
+ message_loop()->Run();
+
+ RemoveObserver(checker_a.get());
+ RemoveObserver(checker_b.get());
+}
+
+} // namespace
+
+} // namespace device_orientation
« no previous file with comments | « chrome/browser/device_orientation/provider_impl.cc ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698