Chromium Code Reviews| Index: cc/blimp/layer_tree_host_remote_unittest.cc |
| diff --git a/cc/blimp/layer_tree_host_remote_unittest.cc b/cc/blimp/layer_tree_host_remote_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..35681384bc78771f6ff78033ea9cb532a682ff57 |
| --- /dev/null |
| +++ b/cc/blimp/layer_tree_host_remote_unittest.cc |
| @@ -0,0 +1,334 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "cc/blimp/layer_tree_host_remote.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/run_loop.h" |
| +#include "base/threading/thread_task_runner_handle.h" |
| +#include "cc/animation/animation_host.h" |
| +#include "cc/blimp/compositor_proto_state_sink.h" |
| +#include "cc/layers/layer.h" |
| +#include "cc/output/begin_frame_args.h" |
| +#include "cc/test/fake_compositor_proto_state_sink.h" |
| +#include "cc/test/stub_layer_tree_host_client.h" |
| +#include "cc/trees/layer_tree_settings.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +using ::testing::_; |
| +using testing::InSequence; |
| +using testing::Mock; |
| +using testing::StrictMock; |
| + |
| +#define EXPECT_BEGIN_MAIN_FRAME(client, num) \ |
| + EXPECT_CALL(client, WillBeginMainFrame()).Times(num); \ |
| + EXPECT_CALL(client, BeginMainFrame(_)).Times(num); \ |
| + EXPECT_CALL(client, DidUpdateLayerTreeHost()).Times(num); \ |
| + EXPECT_CALL(client, WillCommit()).Times(num); \ |
| + EXPECT_CALL(client, DidCommit()).Times(num); \ |
| + EXPECT_CALL(client, DidBeginMainFrame()).Times(num); |
| + |
| +#define EXPECT_BEGIN_MAIN_FRAME_AND_COMMIT(client, num) \ |
| + EXPECT_BEGIN_MAIN_FRAME(client, num) \ |
| + EXPECT_CALL(client, DidCommitAndDrawFrame()).Times(num); \ |
| + EXPECT_CALL(client, DidCompleteSwapBuffers()).Times(num); |
| + |
| +namespace cc { |
| +namespace { |
| + |
| +class UpdateTrackingCompositorProtoStateSink |
| + : public FakeCompositorProtoStateSink { |
| + public: |
| + UpdateTrackingCompositorProtoStateSink() : num_updates_received_(0) {} |
|
danakj
2016/09/26 21:36:54
= default
Khushal
2016/09/27 01:07:50
Done.
|
| + ~UpdateTrackingCompositorProtoStateSink() override {} |
| + |
| + void ProcessCompositorStateUpdate( |
| + std::unique_ptr<CompositorProtoState> compositor_proto_state) override { |
| + num_updates_received_++; |
| + }; |
| + |
| + int num_updates_received() const { return num_updates_received_; } |
| + |
| + private: |
| + int num_updates_received_; |
|
danakj
2016/09/26 21:36:53
= 0
Khushal
2016/09/27 01:07:50
So this always confuses me, what is the preferred
|
| +}; |
| + |
| +class MockLayerTreeHostClient : public StubLayerTreeHostClient { |
| + public: |
| + MockLayerTreeHostClient() {} |
|
danakj
2016/09/26 21:36:53
=default
Khushal
2016/09/27 23:46:56
Done.
|
| + ~MockLayerTreeHostClient() override {} |
|
danakj
2016/09/26 21:36:53
= default?
Khushal
2016/09/27 23:46:56
Done.
|
| + |
| + // LayerTreeHostClient implementation. |
| + MOCK_METHOD0(WillBeginMainFrame, void()); |
| + MOCK_METHOD1(BeginMainFrame, void(const BeginFrameArgs& args)); |
| + MOCK_METHOD0(DidBeginMainFrame, void()); |
| + |
| + void set_update_host_callback(base::Closure callback) { |
|
danakj
2016/09/26 21:36:54
Move this so it's not in the middle of the client
Khushal
2016/09/27 23:46:56
Done.
|
| + update_host_callback_ = callback; |
| + } |
| + |
| + void UpdateLayerTreeHost() override { |
| + update_host_callback_.Run(); |
| + DidUpdateLayerTreeHost(); |
| + } |
| + |
| + MOCK_METHOD0(DidUpdateLayerTreeHost, void()); |
|
danakj
2016/09/26 21:36:53
Group together
Khushal
2016/09/27 01:07:50
Done.
|
| + MOCK_METHOD0(WillCommit, void()); |
| + MOCK_METHOD0(DidCommit, void()); |
| + MOCK_METHOD0(DidCommitAndDrawFrame, void()); |
| + MOCK_METHOD0(DidCompleteSwapBuffers, void()); |
| + |
| + private: |
| + base::Closure update_host_callback_; |
| +}; |
| + |
| +class MockLayer : public Layer { |
| + public: |
| + static scoped_refptr<MockLayer> Create(bool update) { |
|
danakj
2016/09/26 21:36:54
Just make the constructor public pls, delete this
Khushal
2016/09/27 01:07:50
Done.
|
| + return make_scoped_refptr(new MockLayer(update)); |
| + } |
| + |
| + bool Update() override { |
| + did_update_ = true; |
| + return update_; |
| + } |
| + |
| + bool did_update() const { return did_update_; } |
| + |
| + private: |
| + explicit MockLayer(bool update) : update_(update), did_update_(false) {} |
|
danakj
2016/09/26 21:36:53
drop did_update from here
Khushal
2016/09/27 01:07:50
Done.
|
| + ~MockLayer() override {} |
| + |
| + bool update_; |
| + bool did_update_; |
|
danakj
2016/09/26 21:36:53
= false
Khushal
2016/09/27 01:07:50
Done.
|
| +}; |
| + |
| +class MockLayerTree : public LayerTree { |
| + public: |
| + MockLayerTree(std::unique_ptr<AnimationHost> animation_host, |
| + LayerTreeHost* layer_tree_host) |
| + : LayerTree(std::move(animation_host), layer_tree_host) {} |
| + ~MockLayerTree() override {} |
| + |
| + // We don't want tree sync requests to trigger commits. |
|
danakj
2016/09/26 21:36:54
Why not?
Khushal
2016/09/27 01:07:50
Because we always set the root layer at the beginn
|
| + void SetNeedsFullTreeSync() override {} |
| +}; |
| + |
| +class LayerTreeHostRemoteForTesting : public LayerTreeHostRemote { |
| + public: |
| + explicit LayerTreeHostRemoteForTesting(InitParams* params) |
| + : LayerTreeHostRemote( |
| + params, |
| + base::MakeUnique<MockLayerTree>(AnimationHost::CreateMainInstance(), |
| + this)) {} |
| + ~LayerTreeHostRemoteForTesting() override {} |
| +}; |
| + |
| +class LayerTreeHostRemoteTest : public testing::Test { |
| + public: |
| + LayerTreeHostRemoteTest() |
| + : compositor_proto_state_sink_(nullptr), |
|
danakj
2016/09/26 21:36:53
init these where they defined
Khushal
2016/09/27 01:07:50
Done.
|
| + needs_animate_during_main_frame_(false), |
| + needs_commit_during_main_frame_(false) { |
| + mock_layer_tree_host_client_.set_update_host_callback(base::Bind( |
| + &LayerTreeHostRemoteTest::UpdateLayerTreeHost, base::Unretained(this))); |
| + } |
| + ~LayerTreeHostRemoteTest() override {} |
| + |
| + void SetUp() override { |
| + LayerTreeHostRemote::InitParams params; |
| + params.client = &mock_layer_tree_host_client_; |
| + params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); |
| + std::unique_ptr<UpdateTrackingCompositorProtoStateSink> |
| + compositor_proto_state_sink = |
| + base::MakeUnique<UpdateTrackingCompositorProtoStateSink>(); |
| + compositor_proto_state_sink_ = compositor_proto_state_sink.get(); |
| + params.compositor_proto_state_sink = std::move(compositor_proto_state_sink); |
| + LayerTreeSettings settings; |
| + params.settings = &settings; |
| + |
| + layer_tree_host_ = base::MakeUnique<LayerTreeHostRemoteForTesting>(¶ms); |
| + root_layer_ = MockLayer::Create(false); |
| + layer_tree_host_->GetLayerTree()->SetRootLayer(root_layer_); |
| + } |
| + |
| + void TearDown() override { |
| + Mock::VerifyAndClearExpectations(&mock_layer_tree_host_client_); |
| + layer_tree_host_.reset(); |
|
danakj
2016/09/26 21:36:54
= nullptr?
Khushal
2016/09/27 01:07:50
Done.
|
| + root_layer_ = nullptr; |
| + compositor_proto_state_sink_ = nullptr; |
| + } |
| + |
| + void UpdateLayerTreeHost() { |
| + if (needs_animate_during_main_frame_) { |
| + layer_tree_host_->SetNeedsAnimate(); |
| + needs_animate_during_main_frame_ = false; |
| + } |
| + |
| + if (needs_commit_during_main_frame_) { |
| + layer_tree_host_->SetNeedsCommit(); |
| + needs_commit_during_main_frame_ = false; |
| + } |
| + } |
| + |
| + void set_needs_animate_during_main_frame(bool needs) { |
| + needs_animate_during_main_frame_ = needs; |
| + } |
| + |
| + void set_needs_commit_during_main_frame(bool needs) { |
| + needs_commit_during_main_frame_ = needs; |
| + } |
| + |
| + protected: |
| + std::unique_ptr<LayerTreeHostRemote> layer_tree_host_; |
| + StrictMock<MockLayerTreeHostClient> mock_layer_tree_host_client_; |
| + UpdateTrackingCompositorProtoStateSink* compositor_proto_state_sink_; |
|
danakj
2016/09/26 21:36:53
= nullptr
Khushal
2016/09/27 01:07:50
Done.
|
| + scoped_refptr<MockLayer> root_layer_; |
| + |
| + bool needs_animate_during_main_frame_; |
|
danakj
2016/09/26 21:36:53
= false
Khushal
2016/09/27 01:07:50
Done.
|
| + bool needs_commit_during_main_frame_; |
|
danakj
2016/09/26 21:36:53
= false
Khushal
2016/09/27 01:07:50
Done.
|
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(LayerTreeHostRemoteTest); |
| +}; |
| + |
| +TEST_F(LayerTreeHostRemoteTest, BeginMainFrameAnimateOnly) { |
| + // The main frame should run until the animate step only. |
| + InSequence s; |
| + EXPECT_BEGIN_MAIN_FRAME(mock_layer_tree_host_client_, 1); |
| + |
| + int previous_source_frame = layer_tree_host_->SourceFrameNumber(); |
| + layer_tree_host_->SetNeedsAnimate(); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_FALSE(root_layer_->did_update()); |
| + EXPECT_EQ(0, compositor_proto_state_sink_->num_updates_received()); |
| + EXPECT_EQ(++previous_source_frame, layer_tree_host_->SourceFrameNumber()); |
| +} |
| + |
| +TEST_F(LayerTreeHostRemoteTest, BeginMainFrameUpdateLayers) { |
| + // The main frame should run until the update layers step only. |
| + InSequence s; |
| + EXPECT_BEGIN_MAIN_FRAME(mock_layer_tree_host_client_, 1); |
| + |
| + int previous_source_frame = layer_tree_host_->SourceFrameNumber(); |
| + layer_tree_host_->SetNeedsUpdateLayers(); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_TRUE(root_layer_->did_update()); |
| + EXPECT_EQ(0, compositor_proto_state_sink_->num_updates_received()); |
| + EXPECT_EQ(++previous_source_frame, layer_tree_host_->SourceFrameNumber()); |
| +} |
| + |
| +TEST_F(LayerTreeHostRemoteTest, BeginMainFrameCommit) { |
| + // The main frame should run until the commit step. |
| + InSequence s; |
| + EXPECT_BEGIN_MAIN_FRAME_AND_COMMIT(mock_layer_tree_host_client_, 1); |
| + |
| + int previous_source_frame = layer_tree_host_->SourceFrameNumber(); |
| + layer_tree_host_->SetNeedsCommit(); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_TRUE(root_layer_->did_update()); |
| + EXPECT_EQ(1, compositor_proto_state_sink_->num_updates_received()); |
| + EXPECT_EQ(++previous_source_frame, layer_tree_host_->SourceFrameNumber()); |
| +} |
| + |
| +TEST_F(LayerTreeHostRemoteTest, BeginMainFrameMultipleRequests) { |
| + // Multiple BeginMainFrame requests should result in a single main frame |
| + // update. |
| + InSequence s; |
| + EXPECT_BEGIN_MAIN_FRAME_AND_COMMIT(mock_layer_tree_host_client_, 1); |
| + |
| + layer_tree_host_->SetNeedsAnimate(); |
| + layer_tree_host_->SetNeedsUpdateLayers(); |
| + layer_tree_host_->SetNeedsCommit(); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_TRUE(root_layer_->did_update()); |
| + EXPECT_EQ(1, compositor_proto_state_sink_->num_updates_received()); |
| +} |
| + |
| +TEST_F(LayerTreeHostRemoteTest, CommitRequestThenDeferCommits) { |
| + // Make a commit request, followed by a request to defer commits. |
| + layer_tree_host_->SetNeedsCommit(); |
| + layer_tree_host_->SetDeferCommits(true); |
| + |
| + // We should not have seen any BeginMainFrames. |
| + base::RunLoop().RunUntilIdle(); |
| + Mock::VerifyAndClearExpectations(&mock_layer_tree_host_client_); |
| + EXPECT_FALSE(root_layer_->did_update()); |
| + EXPECT_EQ(0, compositor_proto_state_sink_->num_updates_received()); |
| + |
| + // Now enable commits and ensure we see a BeginMainFrame. |
| + layer_tree_host_->SetDeferCommits(false); |
| + InSequence s; |
| + EXPECT_BEGIN_MAIN_FRAME_AND_COMMIT(mock_layer_tree_host_client_, 1); |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_TRUE(root_layer_->did_update()); |
| + EXPECT_EQ(1, compositor_proto_state_sink_->num_updates_received()); |
| +} |
| + |
| +TEST_F(LayerTreeHostRemoteTest, DeferCommitsThenCommitRequest) { |
| + // Defer commits followed by a commit request. |
| + layer_tree_host_->SetDeferCommits(true); |
| + layer_tree_host_->SetNeedsCommit(); |
| + |
| + // We should not have seen any BeginMainFrames. |
| + base::RunLoop().RunUntilIdle(); |
| + Mock::VerifyAndClearExpectations(&mock_layer_tree_host_client_); |
| + EXPECT_FALSE(root_layer_->did_update()); |
| + EXPECT_EQ(0, compositor_proto_state_sink_->num_updates_received()); |
| + |
| + // Now enable commits and ensure we see a BeginMainFrame. |
| + layer_tree_host_->SetDeferCommits(false); |
| + InSequence s; |
| + EXPECT_BEGIN_MAIN_FRAME_AND_COMMIT(mock_layer_tree_host_client_, 1); |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_TRUE(root_layer_->did_update()); |
| + EXPECT_EQ(1, compositor_proto_state_sink_->num_updates_received()); |
| +} |
| + |
| +TEST_F(LayerTreeHostRemoteTest, RequestAnimateDuringMainFrame) { |
| + // An animate request during BeginMainFrame should result in a second main |
| + // frame being scheduled. |
| + set_needs_animate_during_main_frame(true); |
| + EXPECT_BEGIN_MAIN_FRAME(mock_layer_tree_host_client_, 2); |
|
danakj
2016/09/26 21:36:54
maybe use a temp var to point out what this 2 is a
Khushal
2016/09/27 01:07:50
Done.
|
| + |
| + layer_tree_host_->SetNeedsAnimate(); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_FALSE(root_layer_->did_update()); |
| + EXPECT_EQ(0, compositor_proto_state_sink_->num_updates_received()); |
| +} |
| + |
| +TEST_F(LayerTreeHostRemoteTest, RequestCommitDuringMainFrame) { |
| + // A commit request during a BeginMainFrame scheduled for an animate request |
| + // should go till the commit stage. |
| + set_needs_commit_during_main_frame(true); |
| + EXPECT_BEGIN_MAIN_FRAME_AND_COMMIT(mock_layer_tree_host_client_, 1); |
| + |
| + layer_tree_host_->SetNeedsAnimate(); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_TRUE(root_layer_->did_update()); |
| + EXPECT_EQ(1, compositor_proto_state_sink_->num_updates_received()); |
| +} |
| + |
| +TEST_F(LayerTreeHostRemoteTest, RequestCommitDuringLayerUpdates) { |
| + // A layer update during a main frame should result in a commit. |
|
danakj
2016/09/26 21:36:54
The layer add isn't during the main frame here, is
Khushal
2016/09/27 01:07:50
Nope. The main frame wouldn't start until the runl
|
| + scoped_refptr<Layer> child_layer = MockLayer::Create(true); |
| + root_layer_->AddChild(child_layer); |
| + EXPECT_BEGIN_MAIN_FRAME_AND_COMMIT(mock_layer_tree_host_client_, 1); |
| + |
| + layer_tree_host_->SetNeedsUpdateLayers(); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + EXPECT_TRUE(root_layer_->did_update()); |
| + EXPECT_EQ(1, compositor_proto_state_sink_->num_updates_received()); |
| +} |
| + |
| +} // namespace |
| +} // namespace cc |