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

Side by Side Diff: ui/compositor/compositor_unittest.cc

Issue 2773433003: Fix CompositorResizeLock to do something. (Closed)
Patch Set: resizelock: observer-rebase Created 3 years, 8 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdint.h> 5 #include <stdint.h>
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "base/run_loop.h" 8 #include "base/run_loop.h"
9 #include "base/test/test_mock_time_task_runner.h"
9 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
10 #include "cc/output/begin_frame_args.h" 11 #include "cc/output/begin_frame_args.h"
11 #include "cc/surfaces/local_surface_id_allocator.h" 12 #include "cc/surfaces/local_surface_id_allocator.h"
12 #include "cc/surfaces/surface_factory.h" 13 #include "cc/surfaces/surface_factory.h"
13 #include "cc/surfaces/surface_factory_client.h" 14 #include "cc/surfaces/surface_factory_client.h"
14 #include "cc/surfaces/surface_manager.h" 15 #include "cc/surfaces/surface_manager.h"
15 #include "cc/test/begin_frame_args_test.h" 16 #include "cc/test/begin_frame_args_test.h"
16 #include "testing/gmock/include/gmock/gmock.h" 17 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
18 #include "ui/compositor/compositor.h" 19 #include "ui/compositor/compositor.h"
19 #include "ui/compositor/layer.h" 20 #include "ui/compositor/layer.h"
20 #include "ui/compositor/test/context_factories_for_test.h" 21 #include "ui/compositor/test/context_factories_for_test.h"
21 #include "ui/compositor/test/draw_waiter_for_test.h" 22 #include "ui/compositor/test/draw_waiter_for_test.h"
22 23
23 using testing::Mock; 24 using testing::Mock;
24 using testing::_; 25 using testing::_;
25 26
26 namespace ui { 27 namespace ui {
27 namespace { 28 namespace {
28 29
29 // Test fixture for tests that require a ui::Compositor with a real task
30 // runner.
31 class CompositorTest : public testing::Test { 30 class CompositorTest : public testing::Test {
32 public: 31 public:
33 CompositorTest() {} 32 CompositorTest() {}
34 ~CompositorTest() override {} 33 ~CompositorTest() override {}
35 34
36 void SetUp() override { 35 void SetUp() override {
37 task_runner_ = base::ThreadTaskRunnerHandle::Get();
38
39 ui::ContextFactory* context_factory = nullptr; 36 ui::ContextFactory* context_factory = nullptr;
40 ui::ContextFactoryPrivate* context_factory_private = nullptr; 37 ui::ContextFactoryPrivate* context_factory_private = nullptr;
41 ui::InitializeContextFactoryForTests(false, &context_factory, 38 ui::InitializeContextFactoryForTests(false, &context_factory,
42 &context_factory_private); 39 &context_factory_private);
43 40
44 compositor_.reset(new ui::Compositor( 41 compositor_.reset(new ui::Compositor(
45 context_factory_private->AllocateFrameSinkId(), context_factory, 42 context_factory_private->AllocateFrameSinkId(), context_factory,
46 context_factory_private, task_runner_)); 43 context_factory_private, CreateTaskRunner()));
47 compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); 44 compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
48 } 45 }
46
49 void TearDown() override { 47 void TearDown() override {
50 compositor_.reset(); 48 compositor_.reset();
51 ui::TerminateContextFactoryForTests(); 49 ui::TerminateContextFactoryForTests();
52 } 50 }
53 51
54 protected: 52 void DestroyCompositor() { compositor_.reset(); }
55 base::SingleThreadTaskRunner* task_runner() { return task_runner_.get(); } 53
54 protected:
55 virtual scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() = 0;
56
56 ui::Compositor* compositor() { return compositor_.get(); } 57 ui::Compositor* compositor() { return compositor_.get(); }
57 58
58 private: 59 private:
60 std::unique_ptr<ui::Compositor> compositor_;
61
62 DISALLOW_COPY_AND_ASSIGN(CompositorTest);
63 };
64
65 // For tests that control time.
66 class CompositorTestWithMockedTime : public CompositorTest {
67 protected:
68 scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() override {
69 task_runner_ = new base::TestMockTimeTaskRunner;
70 return task_runner_;
71 }
72
73 base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); }
74
75 protected:
76 scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
77 };
78
79 // For tests that run on a real MessageLoop with real time.
80 class CompositorTestWithMessageLoop : public CompositorTest {
81 protected:
82 scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() override {
83 task_runner_ = base::ThreadTaskRunnerHandle::Get();
84 return task_runner_;
85 }
86
87 base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
88
89 private:
59 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 90 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
60 std::unique_ptr<ui::Compositor> compositor_; 91 };
61 92
62 DISALLOW_COPY_AND_ASSIGN(CompositorTest); 93 class CompositorObserverForLocks : public CompositorObserver {
94 public:
95 CompositorObserverForLocks() = default;
96
97 void OnCompositingDidCommit(Compositor* compositor) override {}
98 void OnCompositingStarted(Compositor* compositor,
99 base::TimeTicks start_time) override {}
100 void OnCompositingLockStateChanged(Compositor* compositor) override {
101 changed_ = true;
102 locked_ = compositor->IsLocked();
103 }
104 void OnCompositingShuttingDown(Compositor* compositor) override {}
105
106 bool changed() const { return changed_; }
107 bool locked() const { return locked_; }
108
109 void Reset() { changed_ = false; }
110
111 private:
112 bool changed_ = false;
113 bool locked_ = false;
114 };
115
116 class MockCompositorLockClient
117 : NON_EXPORTED_BASE(public ui::CompositorLockClient) {
118 public:
119 MOCK_METHOD0(CompositorLockTimedOut, void());
63 }; 120 };
64 121
65 } // namespace 122 } // namespace
66 123
67 TEST_F(CompositorTest, LocksTimeOut) { 124 TEST_F(CompositorTestWithMockedTime, LocksAreObserved) {
68 scoped_refptr<ui::CompositorLock> lock; 125 std::unique_ptr<CompositorLock> lock;
69 { 126
70 base::RunLoop run_loop; 127 CompositorObserverForLocks observer;
71 // Ensure that the lock times out by default. 128 compositor()->AddObserver(&observer);
72 lock = compositor()->GetCompositorLock(); 129
130 EXPECT_FALSE(observer.changed());
131
132 lock = compositor()->GetCompositorLock(nullptr, base::TimeDelta());
133 // The observer see that locks changed and that the compositor is locked
134 // at the time.
135 EXPECT_TRUE(observer.changed());
136 EXPECT_TRUE(observer.locked());
137
138 observer.Reset();
139 EXPECT_FALSE(observer.changed());
140
141 lock = nullptr;
142 // The observer see that locks changed and that the compositor is not locked
143 // at the time.
144 EXPECT_TRUE(observer.changed());
145 EXPECT_FALSE(observer.locked());
146
147 compositor()->RemoveObserver(&observer);
148 }
149
150 TEST_F(CompositorTestWithMockedTime, LocksTimeOut) {
151 std::unique_ptr<CompositorLock> lock;
152
153 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(100);
154
155 {
156 testing::StrictMock<MockCompositorLockClient> lock_client;
157 // This lock has a timeout.
158 lock = compositor()->GetCompositorLock(&lock_client, timeout);
73 EXPECT_TRUE(compositor()->IsLocked()); 159 EXPECT_TRUE(compositor()->IsLocked());
74 task_runner()->PostDelayedTask( 160 EXPECT_CALL(lock_client, CompositorLockTimedOut()).Times(1);
75 FROM_HERE, run_loop.QuitClosure(), 161 task_runner()->FastForwardBy(timeout);
76 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs)); 162 task_runner()->RunUntilIdle();
77 run_loop.Run();
78 EXPECT_FALSE(compositor()->IsLocked()); 163 EXPECT_FALSE(compositor()->IsLocked());
79 } 164 }
80 165
81 { 166 {
82 base::RunLoop run_loop; 167 testing::StrictMock<MockCompositorLockClient> lock_client;
83 // Ensure that the lock does not time out when set. 168 // This lock has no timeout.
84 compositor()->SetLocksWillTimeOut(false); 169 lock = compositor()->GetCompositorLock(&lock_client, base::TimeDelta());
85 lock = compositor()->GetCompositorLock();
86 EXPECT_TRUE(compositor()->IsLocked()); 170 EXPECT_TRUE(compositor()->IsLocked());
87 task_runner()->PostDelayedTask( 171 EXPECT_CALL(lock_client, CompositorLockTimedOut()).Times(0);
88 FROM_HERE, run_loop.QuitClosure(), 172 task_runner()->FastForwardBy(timeout);
89 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs)); 173 task_runner()->RunUntilIdle();
90 run_loop.Run();
91 EXPECT_TRUE(compositor()->IsLocked()); 174 EXPECT_TRUE(compositor()->IsLocked());
92 } 175 }
93 } 176 }
94 177
95 TEST_F(CompositorTest, ReleaseWidgetWithOutputSurfaceNeverCreated) { 178 TEST_F(CompositorTestWithMockedTime, MultipleLockClients) {
179 testing::StrictMock<MockCompositorLockClient> lock_client1;
180 std::unique_ptr<CompositorLock> lock1;
181 testing::StrictMock<MockCompositorLockClient> lock_client2;
182 std::unique_ptr<CompositorLock> lock2;
183
184 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
185 // Both locks are grabbed from the Compositor with a separate client.
186 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout);
187 lock2 = compositor()->GetCompositorLock(&lock_client2, timeout);
188 EXPECT_TRUE(compositor()->IsLocked());
189 // Both clients get notified of timeout.
190 EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(1);
191 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
192 task_runner()->FastForwardBy(timeout);
193 task_runner()->RunUntilIdle();
194 EXPECT_FALSE(compositor()->IsLocked());
195 }
196
197 TEST_F(CompositorTestWithMockedTime, ExtendingLifeOfLockDoesntUseDeadClient) {
198 testing::StrictMock<MockCompositorLockClient> lock_client1;
199 std::unique_ptr<CompositorLock> lock1;
200 testing::StrictMock<MockCompositorLockClient> lock_client2;
201 std::unique_ptr<CompositorLock> lock2;
202
203 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
204
205 // One lock is grabbed from the compositor with a client. The other
206 // extends its lifetime past that of the first.
207 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout);
208 EXPECT_TRUE(compositor()->IsLocked());
209
210 // This also locks the compositor and will do so past |lock1| ending.
211 lock2 = compositor()->GetCompositorLock(&lock_client2, timeout);
212 // |lock1| is destroyed, so it won't timeout but |lock2| will.
213 lock1 = nullptr;
214
215 EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
216 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
217 task_runner()->FastForwardBy(timeout);
218 task_runner()->RunUntilIdle();
219
220 EXPECT_FALSE(compositor()->IsLocked());
221 }
222
223 TEST_F(CompositorTestWithMockedTime, AddingLocksDoesNotExtendTimeout) {
224 testing::StrictMock<MockCompositorLockClient> lock_client1;
225 std::unique_ptr<CompositorLock> lock1;
226 testing::StrictMock<MockCompositorLockClient> lock_client2;
227 std::unique_ptr<CompositorLock> lock2;
228
229 base::TimeDelta timeout1 = base::TimeDelta::FromMilliseconds(1);
230 base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
231
232 // The first lock has a short timeout.
233 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout1);
234 EXPECT_TRUE(compositor()->IsLocked());
235
236 // The second lock has a longer timeout, but since a lock is active,
237 // the first one is used for both.
238 lock2 = compositor()->GetCompositorLock(&lock_client2, timeout2);
239
240 EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(1);
241 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
242 task_runner()->FastForwardBy(timeout1);
243 task_runner()->RunUntilIdle();
244 EXPECT_FALSE(compositor()->IsLocked());
245 }
246
247 TEST_F(CompositorTestWithMockedTime, LockIsDestroyedDoesntTimeout) {
248 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
249
250 testing::StrictMock<MockCompositorLockClient> lock_client1;
251 std::unique_ptr<CompositorLock> lock1;
252 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout);
253 EXPECT_TRUE(compositor()->IsLocked());
254 // The CompositorLockClient is destroyed when |lock1| is released.
255 lock1 = nullptr;
256 // The client isn't called as a result.
257 EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
258 task_runner()->FastForwardBy(timeout);
259 task_runner()->RunUntilIdle();
260 EXPECT_FALSE(compositor()->IsLocked());
261 }
262
263 TEST_F(CompositorTestWithMockedTime, TimeoutEndsWhenLockEnds) {
264 testing::StrictMock<MockCompositorLockClient> lock_client1;
265 std::unique_ptr<CompositorLock> lock1;
266 testing::StrictMock<MockCompositorLockClient> lock_client2;
267 std::unique_ptr<CompositorLock> lock2;
268
269 base::TimeDelta timeout1 = base::TimeDelta::FromMilliseconds(1);
270 base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
271
272 // The first lock has a short timeout.
273 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout1);
274 EXPECT_TRUE(compositor()->IsLocked());
275 // But the first lock is ended before timeout.
276 lock1 = nullptr;
277 EXPECT_FALSE(compositor()->IsLocked());
278
279 // The second lock has a longer timeout, and it should use that timeout,
280 // since the first lock is done.
281 lock2 = compositor()->GetCompositorLock(&lock_client2, timeout2);
282 EXPECT_TRUE(compositor()->IsLocked());
283
284 {
285 // The second lock doesn't timeout from the first lock which has ended.
286 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(0);
287 task_runner()->FastForwardBy(timeout1);
288 task_runner()->RunUntilIdle();
289 }
290
291 {
292 // The second lock can still timeout on its own though.
293 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
294 task_runner()->FastForwardBy(timeout2 - timeout1);
295 task_runner()->RunUntilIdle();
296 }
297
298 EXPECT_FALSE(compositor()->IsLocked());
299 }
300
301 TEST_F(CompositorTestWithMockedTime, CompositorLockOutlivesCompositor) {
302 testing::StrictMock<MockCompositorLockClient> lock_client1;
303 std::unique_ptr<CompositorLock> lock1;
304
305 lock1 = compositor()->GetCompositorLock(&lock_client1, base::TimeDelta());
306 // The compositor is destroyed before the lock.
307 DestroyCompositor();
308 // This doesn't crash.
309 lock1 = nullptr;
310 }
311
312 TEST_F(CompositorTestWithMockedTime,
313 ReleaseWidgetWithOutputSurfaceNeverCreated) {
96 compositor()->SetVisible(false); 314 compositor()->SetVisible(false);
97 EXPECT_EQ(gfx::kNullAcceleratedWidget, 315 EXPECT_EQ(gfx::kNullAcceleratedWidget,
98 compositor()->ReleaseAcceleratedWidget()); 316 compositor()->ReleaseAcceleratedWidget());
99 compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); 317 compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
100 compositor()->SetVisible(true); 318 compositor()->SetVisible(true);
101 } 319 }
102 320
103 #if defined(OS_WIN) 321 #if defined(OS_WIN)
104 // TODO(crbug.com/608436): Flaky on windows trybots 322 // TODO(crbug.com/608436): Flaky on windows trybots
105 #define MAYBE_CreateAndReleaseOutputSurface \ 323 #define MAYBE_CreateAndReleaseOutputSurface \
106 DISABLED_CreateAndReleaseOutputSurface 324 DISABLED_CreateAndReleaseOutputSurface
107 #else 325 #else
108 #define MAYBE_CreateAndReleaseOutputSurface CreateAndReleaseOutputSurface 326 #define MAYBE_CreateAndReleaseOutputSurface CreateAndReleaseOutputSurface
109 #endif 327 #endif
110 TEST_F(CompositorTest, MAYBE_CreateAndReleaseOutputSurface) { 328 TEST_F(CompositorTestWithMessageLoop, MAYBE_CreateAndReleaseOutputSurface) {
111 std::unique_ptr<Layer> root_layer(new Layer(ui::LAYER_SOLID_COLOR)); 329 std::unique_ptr<Layer> root_layer(new Layer(ui::LAYER_SOLID_COLOR));
112 root_layer->SetBounds(gfx::Rect(10, 10)); 330 root_layer->SetBounds(gfx::Rect(10, 10));
113 compositor()->SetRootLayer(root_layer.get()); 331 compositor()->SetRootLayer(root_layer.get());
114 compositor()->SetScaleAndSize(1.0f, gfx::Size(10, 10)); 332 compositor()->SetScaleAndSize(1.0f, gfx::Size(10, 10));
115 DCHECK(compositor()->IsVisible()); 333 DCHECK(compositor()->IsVisible());
116 compositor()->ScheduleDraw(); 334 compositor()->ScheduleDraw();
117 DrawWaiterForTest::WaitForCompositingStarted(compositor()); 335 DrawWaiterForTest::WaitForCompositingStarted(compositor());
118 compositor()->SetVisible(false); 336 compositor()->SetVisible(false);
119 EXPECT_EQ(gfx::kNullAcceleratedWidget, 337 EXPECT_EQ(gfx::kNullAcceleratedWidget,
120 compositor()->ReleaseAcceleratedWidget()); 338 compositor()->ReleaseAcceleratedWidget());
121 compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); 339 compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
122 compositor()->SetVisible(true); 340 compositor()->SetVisible(true);
123 compositor()->ScheduleDraw(); 341 compositor()->ScheduleDraw();
124 DrawWaiterForTest::WaitForCompositingStarted(compositor()); 342 DrawWaiterForTest::WaitForCompositingStarted(compositor());
125 compositor()->SetRootLayer(nullptr); 343 compositor()->SetRootLayer(nullptr);
126 } 344 }
127 345
128 } // namespace ui 346 } // namespace ui
OLDNEW
« 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