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

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

Issue 2773433003: Fix CompositorResizeLock to do something. (Closed)
Patch Set: resizelock: outlivescompositorandtimeoutbleeding 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 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/threading/thread_task_runner_handle.h" 9 #include "base/threading/thread_task_runner_handle.h"
10 #include "cc/output/begin_frame_args.h" 10 #include "cc/output/begin_frame_args.h"
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 compositor_.reset(new ui::Compositor( 44 compositor_.reset(new ui::Compositor(
45 context_factory_private->AllocateFrameSinkId(), context_factory, 45 context_factory_private->AllocateFrameSinkId(), context_factory,
46 context_factory_private, task_runner_)); 46 context_factory_private, task_runner_));
47 compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); 47 compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
48 } 48 }
49 void TearDown() override { 49 void TearDown() override {
50 compositor_.reset(); 50 compositor_.reset();
51 ui::TerminateContextFactoryForTests(); 51 ui::TerminateContextFactoryForTests();
52 } 52 }
53 53
54 void DestroyCompositor() { compositor_.reset(); }
55
54 protected: 56 protected:
55 base::SingleThreadTaskRunner* task_runner() { return task_runner_.get(); } 57 base::SingleThreadTaskRunner* task_runner() { return task_runner_.get(); }
56 ui::Compositor* compositor() { return compositor_.get(); } 58 ui::Compositor* compositor() { return compositor_.get(); }
57 59
58 private: 60 private:
59 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 61 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
60 std::unique_ptr<ui::Compositor> compositor_; 62 std::unique_ptr<ui::Compositor> compositor_;
61 63
62 DISALLOW_COPY_AND_ASSIGN(CompositorTest); 64 DISALLOW_COPY_AND_ASSIGN(CompositorTest);
63 }; 65 };
64 66
67 class MockCompositorLockClient
68 : NON_EXPORTED_BASE(public ui::CompositorLockClient) {
69 public:
70 MOCK_METHOD0(CompositorLockTimedOut, void());
71 };
72
65 } // namespace 73 } // namespace
66 74
67 TEST_F(CompositorTest, LocksTimeOut) { 75 TEST_F(CompositorTest, LocksTimeOut) {
68 scoped_refptr<ui::CompositorLock> lock; 76 std::unique_ptr<CompositorLock> lock;
77
78 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(100);
79
69 { 80 {
81 testing::StrictMock<MockCompositorLockClient> lock_client;
70 base::RunLoop run_loop; 82 base::RunLoop run_loop;
71 // Ensure that the lock times out by default. 83 // This lock has a timeout.
72 lock = compositor()->GetCompositorLock(); 84 lock = compositor()->GetCompositorLock(&lock_client, timeout);
73 EXPECT_TRUE(compositor()->IsLocked()); 85 EXPECT_TRUE(compositor()->IsLocked());
74 task_runner()->PostDelayedTask( 86 task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), timeout);
75 FROM_HERE, run_loop.QuitClosure(), 87 EXPECT_CALL(lock_client, CompositorLockTimedOut()).Times(1);
76 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs));
77 run_loop.Run(); 88 run_loop.Run();
78 EXPECT_FALSE(compositor()->IsLocked()); 89 EXPECT_FALSE(compositor()->IsLocked());
79 } 90 }
80 91
81 { 92 {
93 testing::StrictMock<MockCompositorLockClient> lock_client;
82 base::RunLoop run_loop; 94 base::RunLoop run_loop;
83 // Ensure that the lock does not time out when set. 95 // This lock has no timeout.
84 compositor()->SetLocksWillTimeOut(false); 96 lock = compositor()->GetCompositorLock(&lock_client, base::TimeDelta());
85 lock = compositor()->GetCompositorLock();
86 EXPECT_TRUE(compositor()->IsLocked()); 97 EXPECT_TRUE(compositor()->IsLocked());
87 task_runner()->PostDelayedTask( 98 task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), timeout);
88 FROM_HERE, run_loop.QuitClosure(), 99 EXPECT_CALL(lock_client, CompositorLockTimedOut()).Times(0);
89 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs));
90 run_loop.Run(); 100 run_loop.Run();
91 EXPECT_TRUE(compositor()->IsLocked()); 101 EXPECT_TRUE(compositor()->IsLocked());
92 } 102 }
93 } 103 }
94 104
105 TEST_F(CompositorTest, MultipleLockClients) {
106 testing::StrictMock<MockCompositorLockClient> lock_client1;
107 std::unique_ptr<CompositorLock> lock1;
108 testing::StrictMock<MockCompositorLockClient> lock_client2;
109 std::unique_ptr<CompositorLock> lock2;
110
111 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
112 base::RunLoop run_loop;
113 // Both locks are grabbed from the Compositor with a separate client.
114 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout);
115 lock2 = compositor()->GetCompositorLock(&lock_client2, timeout);
116 EXPECT_TRUE(compositor()->IsLocked());
117 task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), timeout);
118 // Both clients get notified of timeout.
119 EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(1);
120 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
121 run_loop.Run();
122 EXPECT_FALSE(compositor()->IsLocked());
123 }
124
125 TEST_F(CompositorTest, ExtendingLifeOfLockDoesntUseDeadClient) {
126 testing::StrictMock<MockCompositorLockClient> lock_client1;
127 std::unique_ptr<CompositorLock> lock1;
128 testing::StrictMock<MockCompositorLockClient> lock_client2;
129 std::unique_ptr<CompositorLock> lock2;
130
131 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
132 base::RunLoop run_loop;
133
134 // One lock is grabbed from the compositor with a client. The other
135 // extends its lifetime past that of the first.
136 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout);
137 EXPECT_TRUE(compositor()->IsLocked());
138
139 // This also locks the compositor and will do so past |lock1| ending.
140 lock2 = compositor()->GetCompositorLock(&lock_client2, timeout);
141 // |lock1| is destroyed, so it won't timeout but |lock2| will.
142 lock1 = nullptr;
143
144 task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), timeout);
145
146 EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
147 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
148 run_loop.Run();
149 EXPECT_FALSE(compositor()->IsLocked());
150 }
151
152 TEST_F(CompositorTest, AddingLocksDoesNotExtendTimeout) {
153 testing::StrictMock<MockCompositorLockClient> lock_client1;
154 std::unique_ptr<CompositorLock> lock1;
155 testing::StrictMock<MockCompositorLockClient> lock_client2;
156 std::unique_ptr<CompositorLock> lock2;
157
158 base::TimeDelta timeout1 = base::TimeDelta::FromMilliseconds(1);
159 base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
160 base::RunLoop run_loop;
161
162 // The first lock has a short timeout.
163 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout1);
164 EXPECT_TRUE(compositor()->IsLocked());
165
166 // The second lock has a longer timeout, but since a lock is active,
167 // the first one is used for both.
168 lock2 = compositor()->GetCompositorLock(&lock_client2, timeout2);
169
170 task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), timeout1);
171
172 EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(1);
173 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
174 run_loop.Run();
175 EXPECT_FALSE(compositor()->IsLocked());
176 }
177
178 TEST_F(CompositorTest, LockIsDestroyedDoesntTimeout) {
179 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
180 base::RunLoop run_loop;
181
182 testing::StrictMock<MockCompositorLockClient> lock_client1;
183 std::unique_ptr<CompositorLock> lock1;
184 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout);
185 EXPECT_TRUE(compositor()->IsLocked());
186 task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), timeout);
187 // The CompositorLockClient is destroyed when |lock1| is released.
188 lock1 = nullptr;
189 // The client isn't called as a result.
190 EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
191 run_loop.Run();
192 EXPECT_FALSE(compositor()->IsLocked());
193 }
194
195 TEST_F(CompositorTest, TimeoutEndsWhenLockEnds) {
196 testing::StrictMock<MockCompositorLockClient> lock_client1;
197 std::unique_ptr<CompositorLock> lock1;
198 testing::StrictMock<MockCompositorLockClient> lock_client2;
199 std::unique_ptr<CompositorLock> lock2;
200
201 base::TimeDelta timeout1 = base::TimeDelta::FromMilliseconds(1);
202 base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
203
204 // The first lock has a short timeout.
205 lock1 = compositor()->GetCompositorLock(&lock_client1, timeout1);
206 EXPECT_TRUE(compositor()->IsLocked());
207 // But the first lock is ended before timeout.
208 lock1 = nullptr;
209 EXPECT_FALSE(compositor()->IsLocked());
210
211 // The second lock has a longer timeout, and it should use that timeout,
212 // since the first lock is done.
213 lock2 = compositor()->GetCompositorLock(&lock_client2, timeout2);
214 EXPECT_TRUE(compositor()->IsLocked());
215
216 {
217 // The second lock doesn't timeout from the first lock which has ended.
218 base::RunLoop run_loop;
219 task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), timeout1);
piman 2017/03/24 19:57:45 This one could in theory be racy causing a flake,
danakj 2017/03/24 20:04:48 Good point, let me look around in base/test/
220
221 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(0);
222 run_loop.Run();
223 }
224
225 {
226 // The second lock can still timeout on its own though.
227 base::RunLoop run_loop;
228 task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), timeout2);
229
230 EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
231 run_loop.Run();
232 }
233
234 EXPECT_FALSE(compositor()->IsLocked());
235 }
236
237 TEST_F(CompositorTest, CompositorLockOutlivesCompositor) {
238 testing::StrictMock<MockCompositorLockClient> lock_client1;
239 std::unique_ptr<CompositorLock> lock1;
240
241 lock1 = compositor()->GetCompositorLock(&lock_client1, base::TimeDelta());
242 // The compositor is destroyed before the lock.
243 DestroyCompositor();
244 // This doesn't crash.
245 lock1 = nullptr;
246 }
247
95 TEST_F(CompositorTest, ReleaseWidgetWithOutputSurfaceNeverCreated) { 248 TEST_F(CompositorTest, ReleaseWidgetWithOutputSurfaceNeverCreated) {
96 compositor()->SetVisible(false); 249 compositor()->SetVisible(false);
97 EXPECT_EQ(gfx::kNullAcceleratedWidget, 250 EXPECT_EQ(gfx::kNullAcceleratedWidget,
98 compositor()->ReleaseAcceleratedWidget()); 251 compositor()->ReleaseAcceleratedWidget());
99 compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); 252 compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
100 compositor()->SetVisible(true); 253 compositor()->SetVisible(true);
101 } 254 }
102 255
103 #if defined(OS_WIN) 256 #if defined(OS_WIN)
104 // TODO(crbug.com/608436): Flaky on windows trybots 257 // TODO(crbug.com/608436): Flaky on windows trybots
(...skipping 14 matching lines...) Expand all
119 EXPECT_EQ(gfx::kNullAcceleratedWidget, 272 EXPECT_EQ(gfx::kNullAcceleratedWidget,
120 compositor()->ReleaseAcceleratedWidget()); 273 compositor()->ReleaseAcceleratedWidget());
121 compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); 274 compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
122 compositor()->SetVisible(true); 275 compositor()->SetVisible(true);
123 compositor()->ScheduleDraw(); 276 compositor()->ScheduleDraw();
124 DrawWaiterForTest::WaitForCompositingEnded(compositor()); 277 DrawWaiterForTest::WaitForCompositingEnded(compositor());
125 compositor()->SetRootLayer(nullptr); 278 compositor()->SetRootLayer(nullptr);
126 } 279 }
127 280
128 } // namespace ui 281 } // 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