| Index: services/ui/surfaces/display_compositor_unittest.cc
|
| diff --git a/services/ui/surfaces/display_compositor_unittest.cc b/services/ui/surfaces/display_compositor_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..16188a4315b04b3978b0d9354d7d2286ab9de300
|
| --- /dev/null
|
| +++ b/services/ui/surfaces/display_compositor_unittest.cc
|
| @@ -0,0 +1,236 @@
|
| +// 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 <inttypes.h>
|
| +
|
| +#include <string>
|
| +#include <utility>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "base/test/test_mock_time_task_runner.h"
|
| +#include "cc/ipc/display_compositor.mojom.h"
|
| +#include "cc/surfaces/surface_id.h"
|
| +#include "cc/surfaces/surface_observer.h"
|
| +#include "mojo/public/cpp/bindings/binding.h"
|
| +#include "mojo/public/cpp/bindings/interface_request.h"
|
| +#include "services/ui/surfaces/display_compositor.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "ui/gfx/geometry/size.h"
|
| +
|
| +using cc::SurfaceId;
|
| +
|
| +namespace ui {
|
| +namespace test {
|
| +namespace {
|
| +
|
| +std::string SurfaceIdString(const cc::SurfaceId& surface_id) {
|
| + return base::StringPrintf("%u:%u:%u", surface_id.frame_sink_id().client_id(),
|
| + surface_id.frame_sink_id().sink_id(),
|
| + surface_id.local_frame_id().local_id());
|
| +}
|
| +
|
| +SurfaceId MakeSurfaceId(uint32_t client_id,
|
| + uint32_t sink_id,
|
| + uint32_t local_id) {
|
| + return SurfaceId(
|
| + cc::FrameSinkId(client_id, sink_id),
|
| + cc::LocalFrameId(local_id, base::UnguessableToken::Create()));
|
| +}
|
| +
|
| +// Test mojom::DisplayCompositorClient that logs OnSurfaceCreated() events.
|
| +class TestDisplayCompositorClient : public cc::mojom::DisplayCompositorClient {
|
| + public:
|
| + TestDisplayCompositorClient() : binding_(this) {}
|
| + ~TestDisplayCompositorClient() override {}
|
| +
|
| + cc::mojom::DisplayCompositorClientPtr GetPtr() {
|
| + return binding_.CreateInterfacePtrAndBind();
|
| + }
|
| +
|
| + std::string events() {
|
| + std::string value = std::move(events_);
|
| + events_.clear();
|
| + return value;
|
| + }
|
| +
|
| + private:
|
| + void AddEvent(const std::string& text) {
|
| + if (!events_.empty())
|
| + events_ += ";";
|
| + events_ += text;
|
| + }
|
| +
|
| + // cc::mojom::DisplayCompositorClient:
|
| + void OnSurfaceCreated(const cc::SurfaceId& surface_id,
|
| + const gfx::Size& frame_size,
|
| + float device_scale_factor) override {
|
| + AddEvent(base::StringPrintf("OnSurfaceCreated(%s)",
|
| + SurfaceIdString(surface_id).c_str()));
|
| + }
|
| +
|
| + mojo::Binding<cc::mojom::DisplayCompositorClient> binding_;
|
| + std::string events_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TestDisplayCompositorClient);
|
| +};
|
| +
|
| +// Test SurfaceReferenceManager that logs AddSurfaceReference() and
|
| +// RemoveSurfaceReference() events.
|
| +class TestSurfaceReferenceManager : public cc::SurfaceReferenceManager {
|
| + public:
|
| + ~TestSurfaceReferenceManager() override {}
|
| +
|
| + const SurfaceId& GetRootSurfaceId() const override { return root_id_; }
|
| +
|
| + void AddSurfaceReference(const SurfaceId& parent_id,
|
| + const SurfaceId& child_id) override {
|
| + AddEvent(base::StringPrintf("Add(%s-%s)",
|
| + SurfaceIdString(parent_id).c_str(),
|
| + SurfaceIdString(child_id).c_str()));
|
| + }
|
| +
|
| + void RemoveSurfaceReference(const SurfaceId& parent_id,
|
| + const SurfaceId& child_id) override {
|
| + AddEvent(base::StringPrintf("Remove(%s-%s)",
|
| + SurfaceIdString(parent_id).c_str(),
|
| + SurfaceIdString(child_id).c_str()));
|
| + }
|
| +
|
| + size_t GetSurfaceReferenceCount(const SurfaceId& surface_id) const override {
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| +
|
| + size_t GetReferencedSurfaceCount(const SurfaceId& surface_id) const override {
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| +
|
| + std::string events() {
|
| + std::string value = std::move(events_);
|
| + events_.clear();
|
| + return value;
|
| + }
|
| +
|
| + private:
|
| + void AddEvent(const std::string& text) {
|
| + if (!events_.empty())
|
| + events_ += ";";
|
| + events_ += text;
|
| + }
|
| +
|
| + const SurfaceId root_id_ = MakeSurfaceId(0, 0, 0);
|
| + std::string events_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +class DisplayCompositorTest : public testing::Test {
|
| + public:
|
| + DisplayCompositorTest() {}
|
| + ~DisplayCompositorTest() override {}
|
| +
|
| + cc::SurfaceObserver* surface_observer() { return display_compositor_.get(); }
|
| +
|
| + void RunUntilIdle() { task_runner_->RunUntilIdle(); }
|
| +
|
| + size_t CountTempReferences() {
|
| + size_t size = 0;
|
| + for (auto& map_entry : display_compositor_->temp_references_) {
|
| + size += map_entry.second.size();
|
| + }
|
| + return size;
|
| + }
|
| +
|
| + // testing::Test:
|
| + void SetUp() override {
|
| + task_runner_ = make_scoped_refptr(new base::TestMockTimeTaskRunner(
|
| + base::Time::Now(), base::TimeTicks::Now()));
|
| + message_loop_.SetTaskRunner(task_runner_);
|
| + display_compositor_ = new DisplayCompositor(client_.GetPtr());
|
| + display_compositor_->set_reference_manager_for_testing(&reference_manager_);
|
| + }
|
| +
|
| + protected:
|
| + base::MessageLoop message_loop_;
|
| + scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
|
| +
|
| + TestDisplayCompositorClient client_;
|
| + TestSurfaceReferenceManager reference_manager_;
|
| + scoped_refptr<DisplayCompositor> display_compositor_;
|
| +};
|
| +
|
| +TEST_F(DisplayCompositorTest, AddSurface) {
|
| + const SurfaceId surface_id = MakeSurfaceId(1, 1, 1);
|
| + surface_observer()->OnSurfaceCreated(surface_id, gfx::Size(1, 1), 1.0f);
|
| + RunUntilIdle();
|
| +
|
| + // Client should get OnSurfaceCreated call and temporary reference added.
|
| + EXPECT_EQ("OnSurfaceCreated(1:1:1)", client_.events());
|
| + EXPECT_EQ("Add(0:0:0-1:1:1)", reference_manager_.events());
|
| + EXPECT_EQ(1u, CountTempReferences());
|
| +
|
| + const SurfaceId parent_id = MakeSurfaceId(2, 1, 1);
|
| + display_compositor_->AddSurfaceReference(parent_id, surface_id);
|
| + RunUntilIdle();
|
| +
|
| + // Real reference is added then temporary reference removed.
|
| + EXPECT_EQ("Add(2:1:1-1:1:1);Remove(0:0:0-1:1:1)",
|
| + reference_manager_.events());
|
| + EXPECT_EQ(0u, CountTempReferences());
|
| +}
|
| +
|
| +TEST_F(DisplayCompositorTest, AddRootReference) {
|
| + const SurfaceId surface_id = MakeSurfaceId(1, 1, 1);
|
| + surface_observer()->OnSurfaceCreated(surface_id, gfx::Size(1, 1), 1.0f);
|
| + RunUntilIdle();
|
| +
|
| + // Temporary reference should be added.
|
| + EXPECT_EQ("Add(0:0:0-1:1:1)", reference_manager_.events());
|
| + EXPECT_EQ(1u, CountTempReferences());
|
| +
|
| + display_compositor_->AddRootSurfaceReference(surface_id);
|
| + RunUntilIdle();
|
| +
|
| + // Adding real reference doesn't need to change anything in
|
| + // SurfaceReferenceManager does remove the temporary reference marker.
|
| + EXPECT_EQ("", reference_manager_.events());
|
| + EXPECT_EQ(0u, CountTempReferences());
|
| +}
|
| +
|
| +TEST_F(DisplayCompositorTest, SkipReference) {
|
| + const SurfaceId surface_id1 = MakeSurfaceId(1, 1, 1);
|
| + const SurfaceId surface_id2 = MakeSurfaceId(1, 1, 2);
|
| +
|
| + // Add two surfaces that have the same FrameSinkId. This would happen when a
|
| + // client submits two CFs in quick succession.
|
| + surface_observer()->OnSurfaceCreated(surface_id1, gfx::Size(1, 1), 1.0f);
|
| + surface_observer()->OnSurfaceCreated(surface_id2, gfx::Size(1, 1), 1.0f);
|
| + RunUntilIdle();
|
| +
|
| + // Client should get OnSurfaceCreated call and temporary reference added for
|
| + // both surfaces.
|
| + EXPECT_EQ("OnSurfaceCreated(1:1:1);OnSurfaceCreated(1:1:2)",
|
| + client_.events());
|
| + EXPECT_EQ("Add(0:0:0-1:1:1);Add(0:0:0-1:1:2)", reference_manager_.events());
|
| + EXPECT_EQ(2u, CountTempReferences());
|
| +
|
| + // Add a reference to the surface with the later LocalFrameId. We will remove
|
| + // the temporary reference to the skipped surface too.
|
| + const SurfaceId parent_id = MakeSurfaceId(2, 1, 1);
|
| + display_compositor_->AddSurfaceReference(parent_id, surface_id2);
|
| + RunUntilIdle();
|
| +
|
| + // Adding real reference doesn't need to change anything in
|
| + // SurfaceReferenceManager does remove the temporary reference marker.
|
| + EXPECT_EQ("Add(2:1:1-1:1:2);Remove(0:0:0-1:1:2);Remove(0:0:0-1:1:1)",
|
| + reference_manager_.events());
|
| + EXPECT_EQ(0u, CountTempReferences());
|
| +}
|
| +
|
| +} // namespace test
|
| +} // namespace ui
|
|
|