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

Unified Diff: ui/compositor/compositor_unittest.cc

Issue 2773433003: Fix CompositorResizeLock to do something. (Closed)
Patch Set: resizelock: 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
Index: ui/compositor/compositor_unittest.cc
diff --git a/ui/compositor/compositor_unittest.cc b/ui/compositor/compositor_unittest.cc
index e62e0b8c430a84131a25aeb4a6c3ee619a3eab11..cf5d43f759ae97003206fbe982f2b5f9173d81c7 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,228 @@ 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 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, 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 +276,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());

Powered by Google App Engine
This is Rietveld 408576698