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

Unified Diff: ui/compositor/compositor_unittest.cc

Issue 2773433003: Fix CompositorResizeLock to do something. (Closed)
Patch Set: resizelock: observer-rebase Created 3 years, 9 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 | « ui/compositor/compositor_lock.cc ('k') | ui/compositor/test/fake_compositor_lock.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/compositor/compositor_unittest.cc
diff --git a/ui/compositor/compositor_unittest.cc b/ui/compositor/compositor_unittest.cc
index 7ab5a5a30b5b21ac877146968355f986d51cdf72..86f2eb3fff4cda9300fb718434c72ea3e1806872 100644
--- a/ui/compositor/compositor_unittest.cc
+++ b/ui/compositor/compositor_unittest.cc
@@ -6,6 +6,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cc/output/begin_frame_args.h"
#include "cc/surfaces/local_surface_id_allocator.h"
@@ -26,16 +27,12 @@ using testing::_;
namespace ui {
namespace {
-// Test fixture for tests that require a ui::Compositor with a real task
-// runner.
class CompositorTest : public testing::Test {
public:
CompositorTest() {}
~CompositorTest() override {}
void SetUp() override {
- task_runner_ = base::ThreadTaskRunnerHandle::Get();
-
ui::ContextFactory* context_factory = nullptr;
ui::ContextFactoryPrivate* context_factory_private = nullptr;
ui::InitializeContextFactoryForTests(false, &context_factory,
@@ -43,56 +40,277 @@ class CompositorTest : public testing::Test {
compositor_.reset(new ui::Compositor(
context_factory_private->AllocateFrameSinkId(), context_factory,
- context_factory_private, task_runner_));
+ context_factory_private, CreateTaskRunner()));
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
}
+
void TearDown() override {
compositor_.reset();
ui::TerminateContextFactoryForTests();
}
+ void DestroyCompositor() { compositor_.reset(); }
+
protected:
- base::SingleThreadTaskRunner* task_runner() { return task_runner_.get(); }
+ virtual scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() = 0;
+
ui::Compositor* compositor() { return compositor_.get(); }
private:
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
std::unique_ptr<ui::Compositor> compositor_;
DISALLOW_COPY_AND_ASSIGN(CompositorTest);
};
+// For tests that control time.
+class CompositorTestWithMockedTime : public CompositorTest {
+ protected:
+ scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() override {
+ task_runner_ = new base::TestMockTimeTaskRunner;
+ return task_runner_;
+ }
+
+ base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); }
+
+ protected:
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
+};
+
+// For tests that run on a real MessageLoop with real time.
+class CompositorTestWithMessageLoop : public CompositorTest {
+ protected:
+ scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() override {
+ task_runner_ = base::ThreadTaskRunnerHandle::Get();
+ return task_runner_;
+ }
+
+ base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+class CompositorObserverForLocks : public CompositorObserver {
+ public:
+ CompositorObserverForLocks() = default;
+
+ void OnCompositingDidCommit(Compositor* compositor) override {}
+ void OnCompositingStarted(Compositor* compositor,
+ base::TimeTicks start_time) override {}
+ void OnCompositingLockStateChanged(Compositor* compositor) override {
+ changed_ = true;
+ locked_ = compositor->IsLocked();
+ }
+ void OnCompositingShuttingDown(Compositor* compositor) override {}
+
+ bool changed() const { return changed_; }
+ bool locked() const { return locked_; }
+
+ void Reset() { changed_ = false; }
+
+ private:
+ bool changed_ = false;
+ bool locked_ = false;
+};
+
+class MockCompositorLockClient
+ : NON_EXPORTED_BASE(public ui::CompositorLockClient) {
+ public:
+ MOCK_METHOD0(CompositorLockTimedOut, void());
+};
+
} // namespace
-TEST_F(CompositorTest, LocksTimeOut) {
- scoped_refptr<ui::CompositorLock> lock;
+TEST_F(CompositorTestWithMockedTime, LocksAreObserved) {
+ std::unique_ptr<CompositorLock> lock;
+
+ CompositorObserverForLocks observer;
+ compositor()->AddObserver(&observer);
+
+ EXPECT_FALSE(observer.changed());
+
+ lock = compositor()->GetCompositorLock(nullptr, base::TimeDelta());
+ // The observer see that locks changed and that the compositor is locked
+ // at the time.
+ EXPECT_TRUE(observer.changed());
+ EXPECT_TRUE(observer.locked());
+
+ observer.Reset();
+ EXPECT_FALSE(observer.changed());
+
+ lock = nullptr;
+ // The observer see that locks changed and that the compositor is not locked
+ // at the time.
+ EXPECT_TRUE(observer.changed());
+ EXPECT_FALSE(observer.locked());
+
+ compositor()->RemoveObserver(&observer);
+}
+
+TEST_F(CompositorTestWithMockedTime, LocksTimeOut) {
+ std::unique_ptr<CompositorLock> lock;
+
+ base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(100);
+
{
- base::RunLoop run_loop;
- // Ensure that the lock times out by default.
- lock = compositor()->GetCompositorLock();
+ testing::StrictMock<MockCompositorLockClient> lock_client;
+ // This lock has a timeout.
+ lock = compositor()->GetCompositorLock(&lock_client, timeout);
EXPECT_TRUE(compositor()->IsLocked());
- task_runner()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(),
- base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs));
- run_loop.Run();
+ EXPECT_CALL(lock_client, CompositorLockTimedOut()).Times(1);
+ task_runner()->FastForwardBy(timeout);
+ task_runner()->RunUntilIdle();
EXPECT_FALSE(compositor()->IsLocked());
}
{
- base::RunLoop run_loop;
- // Ensure that the lock does not time out when set.
- compositor()->SetLocksWillTimeOut(false);
- lock = compositor()->GetCompositorLock();
+ testing::StrictMock<MockCompositorLockClient> lock_client;
+ // This lock has no timeout.
+ lock = compositor()->GetCompositorLock(&lock_client, base::TimeDelta());
EXPECT_TRUE(compositor()->IsLocked());
- task_runner()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(),
- base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs));
- run_loop.Run();
+ EXPECT_CALL(lock_client, CompositorLockTimedOut()).Times(0);
+ task_runner()->FastForwardBy(timeout);
+ task_runner()->RunUntilIdle();
EXPECT_TRUE(compositor()->IsLocked());
}
}
-TEST_F(CompositorTest, ReleaseWidgetWithOutputSurfaceNeverCreated) {
+TEST_F(CompositorTestWithMockedTime, MultipleLockClients) {
+ testing::StrictMock<MockCompositorLockClient> lock_client1;
+ std::unique_ptr<CompositorLock> lock1;
+ testing::StrictMock<MockCompositorLockClient> lock_client2;
+ std::unique_ptr<CompositorLock> lock2;
+
+ base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
+ // Both locks are grabbed from the Compositor with a separate client.
+ lock1 = compositor()->GetCompositorLock(&lock_client1, timeout);
+ lock2 = compositor()->GetCompositorLock(&lock_client2, timeout);
+ EXPECT_TRUE(compositor()->IsLocked());
+ // Both clients get notified of timeout.
+ EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(1);
+ EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
+ task_runner()->FastForwardBy(timeout);
+ task_runner()->RunUntilIdle();
+ EXPECT_FALSE(compositor()->IsLocked());
+}
+
+TEST_F(CompositorTestWithMockedTime, ExtendingLifeOfLockDoesntUseDeadClient) {
+ testing::StrictMock<MockCompositorLockClient> lock_client1;
+ std::unique_ptr<CompositorLock> lock1;
+ testing::StrictMock<MockCompositorLockClient> lock_client2;
+ std::unique_ptr<CompositorLock> lock2;
+
+ base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
+
+ // One lock is grabbed from the compositor with a client. The other
+ // extends its lifetime past that of the first.
+ lock1 = compositor()->GetCompositorLock(&lock_client1, timeout);
+ EXPECT_TRUE(compositor()->IsLocked());
+
+ // This also locks the compositor and will do so past |lock1| ending.
+ lock2 = compositor()->GetCompositorLock(&lock_client2, timeout);
+ // |lock1| is destroyed, so it won't timeout but |lock2| will.
+ lock1 = nullptr;
+
+ EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
+ EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
+ task_runner()->FastForwardBy(timeout);
+ task_runner()->RunUntilIdle();
+
+ EXPECT_FALSE(compositor()->IsLocked());
+}
+
+TEST_F(CompositorTestWithMockedTime, AddingLocksDoesNotExtendTimeout) {
+ testing::StrictMock<MockCompositorLockClient> lock_client1;
+ std::unique_ptr<CompositorLock> lock1;
+ testing::StrictMock<MockCompositorLockClient> lock_client2;
+ std::unique_ptr<CompositorLock> lock2;
+
+ base::TimeDelta timeout1 = base::TimeDelta::FromMilliseconds(1);
+ base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
+
+ // The first lock has a short timeout.
+ lock1 = compositor()->GetCompositorLock(&lock_client1, timeout1);
+ EXPECT_TRUE(compositor()->IsLocked());
+
+ // The second lock has a longer timeout, but since a lock is active,
+ // the first one is used for both.
+ lock2 = compositor()->GetCompositorLock(&lock_client2, timeout2);
+
+ EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(1);
+ EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
+ task_runner()->FastForwardBy(timeout1);
+ task_runner()->RunUntilIdle();
+ EXPECT_FALSE(compositor()->IsLocked());
+}
+
+TEST_F(CompositorTestWithMockedTime, LockIsDestroyedDoesntTimeout) {
+ base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
+
+ testing::StrictMock<MockCompositorLockClient> lock_client1;
+ std::unique_ptr<CompositorLock> lock1;
+ lock1 = compositor()->GetCompositorLock(&lock_client1, timeout);
+ EXPECT_TRUE(compositor()->IsLocked());
+ // The CompositorLockClient is destroyed when |lock1| is released.
+ lock1 = nullptr;
+ // The client isn't called as a result.
+ EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
+ task_runner()->FastForwardBy(timeout);
+ task_runner()->RunUntilIdle();
+ EXPECT_FALSE(compositor()->IsLocked());
+}
+
+TEST_F(CompositorTestWithMockedTime, TimeoutEndsWhenLockEnds) {
+ testing::StrictMock<MockCompositorLockClient> lock_client1;
+ std::unique_ptr<CompositorLock> lock1;
+ testing::StrictMock<MockCompositorLockClient> lock_client2;
+ std::unique_ptr<CompositorLock> lock2;
+
+ base::TimeDelta timeout1 = base::TimeDelta::FromMilliseconds(1);
+ base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
+
+ // The first lock has a short timeout.
+ lock1 = compositor()->GetCompositorLock(&lock_client1, timeout1);
+ EXPECT_TRUE(compositor()->IsLocked());
+ // But the first lock is ended before timeout.
+ lock1 = nullptr;
+ EXPECT_FALSE(compositor()->IsLocked());
+
+ // The second lock has a longer timeout, and it should use that timeout,
+ // since the first lock is done.
+ lock2 = compositor()->GetCompositorLock(&lock_client2, timeout2);
+ EXPECT_TRUE(compositor()->IsLocked());
+
+ {
+ // The second lock doesn't timeout from the first lock which has ended.
+ EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(0);
+ task_runner()->FastForwardBy(timeout1);
+ task_runner()->RunUntilIdle();
+ }
+
+ {
+ // The second lock can still timeout on its own though.
+ EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
+ task_runner()->FastForwardBy(timeout2 - timeout1);
+ task_runner()->RunUntilIdle();
+ }
+
+ EXPECT_FALSE(compositor()->IsLocked());
+}
+
+TEST_F(CompositorTestWithMockedTime, CompositorLockOutlivesCompositor) {
+ testing::StrictMock<MockCompositorLockClient> lock_client1;
+ std::unique_ptr<CompositorLock> lock1;
+
+ lock1 = compositor()->GetCompositorLock(&lock_client1, base::TimeDelta());
+ // The compositor is destroyed before the lock.
+ DestroyCompositor();
+ // This doesn't crash.
+ lock1 = nullptr;
+}
+
+TEST_F(CompositorTestWithMockedTime,
+ ReleaseWidgetWithOutputSurfaceNeverCreated) {
compositor()->SetVisible(false);
EXPECT_EQ(gfx::kNullAcceleratedWidget,
compositor()->ReleaseAcceleratedWidget());
@@ -107,7 +325,7 @@ TEST_F(CompositorTest, ReleaseWidgetWithOutputSurfaceNeverCreated) {
#else
#define MAYBE_CreateAndReleaseOutputSurface CreateAndReleaseOutputSurface
#endif
-TEST_F(CompositorTest, MAYBE_CreateAndReleaseOutputSurface) {
+TEST_F(CompositorTestWithMessageLoop, MAYBE_CreateAndReleaseOutputSurface) {
std::unique_ptr<Layer> root_layer(new Layer(ui::LAYER_SOLID_COLOR));
root_layer->SetBounds(gfx::Rect(10, 10));
compositor()->SetRootLayer(root_layer.get());
« no previous file with comments | « ui/compositor/compositor_lock.cc ('k') | ui/compositor/test/fake_compositor_lock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698