Reenable NullOpenerRedirectForksProcess, as the offending patch has been reverted
[chromium-blink-merge.git] / cc / tree_synchronizer_unittest.cc
blobae274433645831461a38c92afe2caeccb9cf8016
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/tree_synchronizer.h"
7 #include <algorithm>
9 #include "cc/layer.h"
10 #include "cc/layer_animation_controller.h"
11 #include "cc/layer_impl.h"
12 #include "cc/proxy.h"
13 #include "cc/single_thread_proxy.h"
14 #include "cc/test/animation_test_common.h"
15 #include "cc/test/fake_proxy.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 using namespace WebKitTests;
20 namespace cc {
21 namespace {
23 class MockLayerImpl : public LayerImpl {
24 public:
25 static scoped_ptr<MockLayerImpl> create(int layerId)
27 return make_scoped_ptr(new MockLayerImpl(layerId));
29 virtual ~MockLayerImpl()
31 if (m_layerImplDestructionList)
32 m_layerImplDestructionList->push_back(id());
35 void setLayerImplDestructionList(std::vector<int>* list) { m_layerImplDestructionList = list; }
37 private:
38 MockLayerImpl(int layerId)
39 : LayerImpl(layerId)
40 , m_layerImplDestructionList(0)
44 std::vector<int>* m_layerImplDestructionList;
47 class MockLayer : public Layer {
48 public:
49 static scoped_refptr<MockLayer> create(std::vector<int>* layerImplDestructionList)
51 return make_scoped_refptr(new MockLayer(layerImplDestructionList));
54 virtual scoped_ptr<LayerImpl> createLayerImpl() OVERRIDE
56 return MockLayerImpl::create(m_layerId).PassAs<LayerImpl>();
59 virtual void pushPropertiesTo(LayerImpl* layerImpl) OVERRIDE
61 Layer::pushPropertiesTo(layerImpl);
63 MockLayerImpl* mockLayerImpl = static_cast<MockLayerImpl*>(layerImpl);
64 mockLayerImpl->setLayerImplDestructionList(m_layerImplDestructionList);
67 private:
68 MockLayer(std::vector<int>* layerImplDestructionList)
69 : Layer()
70 , m_layerImplDestructionList(layerImplDestructionList)
73 virtual ~MockLayer() { }
75 std::vector<int>* m_layerImplDestructionList;
78 class FakeLayerAnimationController : public LayerAnimationController {
79 public:
80 static scoped_ptr<FakeLayerAnimationController> create(LayerAnimationControllerClient* client)
82 return make_scoped_ptr(new FakeLayerAnimationController(client));
85 bool synchronizedAnimations() const { return m_synchronizedAnimations; }
87 private:
88 explicit FakeLayerAnimationController(LayerAnimationControllerClient* client)
89 : LayerAnimationController(client)
90 , m_synchronizedAnimations(false)
94 virtual void pushAnimationUpdatesTo(LayerAnimationController* controllerImpl)
96 LayerAnimationController::pushAnimationUpdatesTo(controllerImpl);
97 m_synchronizedAnimations = true;
100 bool m_synchronizedAnimations;
103 void expectTreesAreIdentical(Layer* layer, LayerImpl* layerImpl, LayerTreeHostImpl* hostImpl)
105 ASSERT_TRUE(layer);
106 ASSERT_TRUE(layerImpl);
108 EXPECT_EQ(layer->id(), layerImpl->id());
109 EXPECT_EQ(layerImpl->layerTreeHostImpl(), hostImpl);
111 EXPECT_EQ(layer->nonFastScrollableRegion(), layerImpl->nonFastScrollableRegion());
113 ASSERT_EQ(!!layer->maskLayer(), !!layerImpl->maskLayer());
114 if (layer->maskLayer())
115 expectTreesAreIdentical(layer->maskLayer(), layerImpl->maskLayer(), hostImpl);
117 ASSERT_EQ(!!layer->replicaLayer(), !!layerImpl->replicaLayer());
118 if (layer->replicaLayer())
119 expectTreesAreIdentical(layer->replicaLayer(), layerImpl->replicaLayer(), hostImpl);
121 const std::vector<scoped_refptr<Layer> >& layerChildren = layer->children();
122 const ScopedPtrVector<LayerImpl>& layerImplChildren = layerImpl->children();
124 ASSERT_EQ(layerChildren.size(), layerImplChildren.size());
126 for (size_t i = 0; i < layerChildren.size(); ++i)
127 expectTreesAreIdentical(layerChildren[i].get(), layerImplChildren[i], hostImpl);
130 // Attempts to synchronizes a null tree. This should not crash, and should
131 // return a null tree.
132 TEST(TreeSynchronizerTest, syncNullTree)
134 scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(0, scoped_ptr<LayerImpl>(), 0);
136 EXPECT_TRUE(!layerImplTreeRoot.get());
139 // Constructs a very simple tree and synchronizes it without trying to reuse any preexisting layers.
140 TEST(TreeSynchronizerTest, syncSimpleTreeFromEmpty)
142 LayerTreeSettings settings;
143 FakeProxy proxy(scoped_ptr<Thread>(NULL));
144 DebugScopedSetImplThread impl(&proxy);
145 scoped_ptr<LayerTreeHostImpl> hostImpl = LayerTreeHostImpl::create(settings, 0, &proxy);
147 scoped_refptr<Layer> layerTreeRoot = Layer::create();
148 layerTreeRoot->addChild(Layer::create());
149 layerTreeRoot->addChild(Layer::create());
151 scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), hostImpl.get());
153 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
156 // Constructs a very simple tree and synchronizes it attempting to reuse some layers
157 TEST(TreeSynchronizerTest, syncSimpleTreeReusingLayers)
159 std::vector<int> layerImplDestructionList;
161 LayerTreeSettings settings;
162 FakeProxy proxy(scoped_ptr<Thread>(NULL));
163 DebugScopedSetImplThread impl(&proxy);
164 scoped_ptr<LayerTreeHostImpl> hostImpl = LayerTreeHostImpl::create(settings, 0, &proxy);
166 scoped_refptr<Layer> layerTreeRoot = MockLayer::create(&layerImplDestructionList);
167 layerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList));
168 layerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList));
170 scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), hostImpl.get());
171 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
173 // Add a new layer to the Layer side
174 layerTreeRoot->children()[0]->addChild(MockLayer::create(&layerImplDestructionList));
175 // Remove one.
176 layerTreeRoot->children()[1]->removeFromParent();
177 int secondLayerImplId = layerImplTreeRoot->children()[1]->id();
179 // Synchronize again. After the sync the trees should be equivalent and we should have created and destroyed one LayerImpl.
180 layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), hostImpl.get());
181 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
183 ASSERT_EQ(1u, layerImplDestructionList.size());
184 EXPECT_EQ(secondLayerImplId, layerImplDestructionList[0]);
187 // Constructs a very simple tree and checks that a stacking-order change is tracked properly.
188 TEST(TreeSynchronizerTest, syncSimpleTreeAndTrackStackingOrderChange)
190 std::vector<int> layerImplDestructionList;
192 LayerTreeSettings settings;
193 FakeProxy proxy(scoped_ptr<Thread>(NULL));
194 DebugScopedSetImplThread impl(&proxy);
195 scoped_ptr<LayerTreeHostImpl> hostImpl = LayerTreeHostImpl::create(settings, 0, &proxy);
197 // Set up the tree and sync once. child2 needs to be synced here, too, even though we
198 // remove it to set up the intended scenario.
199 scoped_refptr<Layer> layerTreeRoot = MockLayer::create(&layerImplDestructionList);
200 scoped_refptr<Layer> child2 = MockLayer::create(&layerImplDestructionList);
201 layerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList));
202 layerTreeRoot->addChild(child2);
203 scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), hostImpl.get());
204 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
205 layerImplTreeRoot->resetAllChangeTrackingForSubtree();
207 // re-insert the layer and sync again.
208 child2->removeFromParent();
209 layerTreeRoot->addChild(child2);
210 layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), hostImpl.get());
211 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
213 // Check that the impl thread properly tracked the change.
214 EXPECT_FALSE(layerImplTreeRoot->layerPropertyChanged());
215 EXPECT_FALSE(layerImplTreeRoot->children()[0]->layerPropertyChanged());
216 EXPECT_TRUE(layerImplTreeRoot->children()[1]->layerPropertyChanged());
219 TEST(TreeSynchronizerTest, syncSimpleTreeAndProperties)
221 LayerTreeSettings settings;
222 FakeProxy proxy(scoped_ptr<Thread>(NULL));
223 DebugScopedSetImplThread impl(&proxy);
224 scoped_ptr<LayerTreeHostImpl> hostImpl = LayerTreeHostImpl::create(settings, 0, &proxy);
226 scoped_refptr<Layer> layerTreeRoot = Layer::create();
227 layerTreeRoot->addChild(Layer::create());
228 layerTreeRoot->addChild(Layer::create());
230 // Pick some random properties to set. The values are not important, we're just testing that at least some properties are making it through.
231 gfx::PointF rootPosition = gfx::PointF(2.3f, 7.4f);
232 layerTreeRoot->setPosition(rootPosition);
234 float firstChildOpacity = 0.25f;
235 layerTreeRoot->children()[0]->setOpacity(firstChildOpacity);
237 gfx::Size secondChildBounds = gfx::Size(25, 53);
238 layerTreeRoot->children()[1]->setBounds(secondChildBounds);
240 scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), hostImpl.get());
241 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
243 // Check that the property values we set on the Layer tree are reflected in the LayerImpl tree.
244 gfx::PointF rootLayerImplPosition = layerImplTreeRoot->position();
245 EXPECT_EQ(rootPosition.x(), rootLayerImplPosition.x());
246 EXPECT_EQ(rootPosition.y(), rootLayerImplPosition.y());
248 EXPECT_EQ(firstChildOpacity, layerImplTreeRoot->children()[0]->opacity());
250 gfx::Size secondLayerImplChildBounds = layerImplTreeRoot->children()[1]->bounds();
251 EXPECT_EQ(secondChildBounds.width(), secondLayerImplChildBounds.width());
252 EXPECT_EQ(secondChildBounds.height(), secondLayerImplChildBounds.height());
255 TEST(TreeSynchronizerTest, reuseLayerImplsAfterStructuralChange)
257 std::vector<int> layerImplDestructionList;
259 LayerTreeSettings settings;
260 FakeProxy proxy(scoped_ptr<Thread>(NULL));
261 DebugScopedSetImplThread impl(&proxy);
262 scoped_ptr<LayerTreeHostImpl> hostImpl = LayerTreeHostImpl::create(settings, 0, &proxy);
264 // Set up a tree with this sort of structure:
265 // root --- A --- B ---+--- C
266 // |
267 // +--- D
268 scoped_refptr<Layer> layerTreeRoot = MockLayer::create(&layerImplDestructionList);
269 layerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList));
271 scoped_refptr<Layer> layerA = layerTreeRoot->children()[0].get();
272 layerA->addChild(MockLayer::create(&layerImplDestructionList));
274 scoped_refptr<Layer> layerB = layerA->children()[0].get();
275 layerB->addChild(MockLayer::create(&layerImplDestructionList));
277 scoped_refptr<Layer> layerC = layerB->children()[0].get();
278 layerB->addChild(MockLayer::create(&layerImplDestructionList));
279 scoped_refptr<Layer> layerD = layerB->children()[1].get();
281 scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), hostImpl.get());
282 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
284 // Now restructure the tree to look like this:
285 // root --- D ---+--- A
286 // |
287 // +--- C --- B
288 layerTreeRoot->removeAllChildren();
289 layerD->removeAllChildren();
290 layerTreeRoot->addChild(layerD);
291 layerA->removeAllChildren();
292 layerD->addChild(layerA);
293 layerC->removeAllChildren();
294 layerD->addChild(layerC);
295 layerB->removeAllChildren();
296 layerC->addChild(layerB);
298 // After another synchronize our trees should match and we should not have destroyed any LayerImpls
299 layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), hostImpl.get());
300 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
302 EXPECT_EQ(0u, layerImplDestructionList.size());
305 // Constructs a very simple tree, synchronizes it, then synchronizes to a totally new tree. All layers from the old tree should be deleted.
306 TEST(TreeSynchronizerTest, syncSimpleTreeThenDestroy)
308 std::vector<int> layerImplDestructionList;
310 LayerTreeSettings settings;
311 FakeProxy proxy(scoped_ptr<Thread>(NULL));
312 DebugScopedSetImplThread impl(&proxy);
313 scoped_ptr<LayerTreeHostImpl> hostImpl = LayerTreeHostImpl::create(settings, 0, &proxy);
315 scoped_refptr<Layer> oldLayerTreeRoot = MockLayer::create(&layerImplDestructionList);
316 oldLayerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList));
317 oldLayerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList));
319 int oldTreeRootLayerId = oldLayerTreeRoot->id();
320 int oldTreeFirstChildLayerId = oldLayerTreeRoot->children()[0]->id();
321 int oldTreeSecondChildLayerId = oldLayerTreeRoot->children()[1]->id();
323 scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(oldLayerTreeRoot.get(), scoped_ptr<LayerImpl>(), hostImpl.get());
324 expectTreesAreIdentical(oldLayerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
326 // Remove all children on the Layer side.
327 oldLayerTreeRoot->removeAllChildren();
329 // Synchronize again. After the sync all LayerImpls from the old tree should be deleted.
330 scoped_refptr<Layer> newLayerTreeRoot = Layer::create();
331 layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(newLayerTreeRoot.get(), layerImplTreeRoot.Pass(), hostImpl.get());
332 expectTreesAreIdentical(newLayerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
334 ASSERT_EQ(3u, layerImplDestructionList.size());
336 EXPECT_TRUE(std::find(layerImplDestructionList.begin(), layerImplDestructionList.end(), oldTreeRootLayerId) != layerImplDestructionList.end());
337 EXPECT_TRUE(std::find(layerImplDestructionList.begin(), layerImplDestructionList.end(), oldTreeFirstChildLayerId) != layerImplDestructionList.end());
338 EXPECT_TRUE(std::find(layerImplDestructionList.begin(), layerImplDestructionList.end(), oldTreeSecondChildLayerId) != layerImplDestructionList.end());
341 // Constructs+syncs a tree with mask, replica, and replica mask layers.
342 TEST(TreeSynchronizerTest, syncMaskReplicaAndReplicaMaskLayers)
344 LayerTreeSettings settings;
345 FakeProxy proxy(scoped_ptr<Thread>(NULL));
346 DebugScopedSetImplThread impl(&proxy);
347 scoped_ptr<LayerTreeHostImpl> hostImpl = LayerTreeHostImpl::create(settings, 0, &proxy);
349 scoped_refptr<Layer> layerTreeRoot = Layer::create();
350 layerTreeRoot->addChild(Layer::create());
351 layerTreeRoot->addChild(Layer::create());
352 layerTreeRoot->addChild(Layer::create());
354 // First child gets a mask layer.
355 scoped_refptr<Layer> maskLayer = Layer::create();
356 layerTreeRoot->children()[0]->setMaskLayer(maskLayer.get());
358 // Second child gets a replica layer.
359 scoped_refptr<Layer> replicaLayer = Layer::create();
360 layerTreeRoot->children()[1]->setReplicaLayer(replicaLayer.get());
362 // Third child gets a replica layer with a mask layer.
363 scoped_refptr<Layer> replicaLayerWithMask = Layer::create();
364 scoped_refptr<Layer> replicaMaskLayer = Layer::create();
365 replicaLayerWithMask->setMaskLayer(replicaMaskLayer.get());
366 layerTreeRoot->children()[2]->setReplicaLayer(replicaLayerWithMask.get());
368 scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), hostImpl.get());
370 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
372 // Remove the mask layer.
373 layerTreeRoot->children()[0]->setMaskLayer(0);
374 layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), hostImpl.get());
375 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
377 // Remove the replica layer.
378 layerTreeRoot->children()[1]->setReplicaLayer(0);
379 layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), hostImpl.get());
380 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
382 // Remove the replica mask.
383 replicaLayerWithMask->setMaskLayer(0);
384 layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), hostImpl.get());
385 expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), hostImpl.get());
388 TEST(TreeSynchronizerTest, synchronizeAnimations)
390 LayerTreeSettings settings;
391 FakeProxy proxy(scoped_ptr<Thread>(NULL));
392 DebugScopedSetImplThread impl(&proxy);
393 scoped_ptr<LayerTreeHostImpl> hostImpl = LayerTreeHostImpl::create(settings, 0, &proxy);
395 scoped_refptr<Layer> layerTreeRoot = Layer::create();
397 FakeLayerAnimationControllerClient dummy;
398 layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create(&dummy).PassAs<LayerAnimationController>());
400 EXPECT_FALSE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations());
402 scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), hostImpl.get());
403 layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), hostImpl.get());
405 EXPECT_TRUE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations());
408 } // namespace
409 } // namespace cc