Chromium Code Reviews| Index: blimp/client/core/compositor/delegated_output_surface_unittest.cc |
| diff --git a/blimp/client/core/compositor/delegated_output_surface_unittest.cc b/blimp/client/core/compositor/delegated_output_surface_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..59fbc8e2023920143598268e919e5ecdf3333014 |
| --- /dev/null |
| +++ b/blimp/client/core/compositor/delegated_output_surface_unittest.cc |
| @@ -0,0 +1,244 @@ |
| +// 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 "blimp/client/core/compositor/delegated_output_surface.h" |
| + |
| +#include "base/memory/ptr_util.h" |
| +#include "base/synchronization/waitable_event.h" |
| +#include "base/threading/thread_task_runner_handle.h" |
| +#include "cc/output/compositor_frame.h" |
| +#include "cc/test/fake_output_surface_client.h" |
| +#include "cc/test/test_context_provider.h" |
| +#include "cc/test/test_context_support.h" |
| +#include "cc/test/test_gles2_interface.h" |
| +#include "cc/test/test_web_graphics_context_3d.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace blimp { |
| +namespace client { |
| +namespace { |
| + |
| +class FakeBlimpOutputSurfaceClient : public BlimpOutputSurfaceClient { |
| + public: |
| + FakeBlimpOutputSurfaceClient() |
| + : output_surface_(nullptr), surfaces_bound_(0), swap_count_(0) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + } |
| + |
| + ~FakeBlimpOutputSurfaceClient() override { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + EXPECT_EQ(nullptr, output_surface_); |
| + } |
| + |
| + void BindToOutputSurface(BlimpOutputSurface* output_surface) override { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + EXPECT_EQ(nullptr, output_surface_); |
| + output_surface_ = output_surface; |
| + surfaces_bound_++; |
| + } |
| + |
| + void SwapCompositorFrame(cc::CompositorFrame frame) override { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + swap_count_++; |
| + output_surface_->ReclaimCompositorResources(cc::ReturnedResourceArray()); |
| + } |
| + |
| + void UnbindOutputSurface(BlimpOutputSurface* output_surface) override { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + EXPECT_EQ(output_surface, output_surface_); |
| + output_surface_ = nullptr; |
| + } |
| + |
| + int surfaces_bound() const { return surfaces_bound_; } |
| + int swap_count() const { return swap_count_; } |
| + |
| + private: |
| + BlimpOutputSurface* output_surface_; |
| + int surfaces_bound_; |
| + int swap_count_; |
| + base::ThreadChecker thread_checker_; |
| +}; |
| + |
| +class TestContextProvider : public cc::TestContextProvider { |
| + public: |
| + static scoped_refptr<TestContextProvider> Create(bool bind_should_fail) { |
| + return new TestContextProvider(bind_should_fail); |
| + } |
| + |
| + protected: |
| + explicit TestContextProvider(bool bind_should_fail) |
| + : cc::TestContextProvider(base::MakeUnique<cc::TestContextSupport>(), |
| + base::MakeUnique<cc::TestGLES2Interface>(), |
| + cc::TestWebGraphicsContext3D::Create()), |
| + bind_should_fail_(bind_should_fail) {} |
| + |
| + ~TestContextProvider() override {} |
| + |
| + bool BindToCurrentThread() override { |
| + if (bind_should_fail_) |
| + return false; |
| + return cc::TestContextProvider::BindToCurrentThread(); |
| + } |
| + |
| + private: |
| + const bool bind_should_fail_; |
| +}; |
| + |
| +class TestDelegatedOutputSurface : public DelegatedOutputSurface { |
| + public: |
| + TestDelegatedOutputSurface( |
| + scoped_refptr<cc::ContextProvider> compositor_context_provider, |
| + scoped_refptr<cc::ContextProvider> worker_context_provider, |
| + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, |
| + BlimpOutputSurfaceClient* client) |
| + : DelegatedOutputSurface(compositor_context_provider, |
| + worker_context_provider, |
| + main_task_runner, |
| + compositor_task_runner, |
| + client), |
| + pending_swap_ack_count_(0), |
| + unclaimed_resources_count_(0) {} |
| + |
| + void DoSwapBuffers() { |
| + DelegatedOutputSurface::SwapBuffers(cc::CompositorFrame()); |
| + unclaimed_resources_count_++; |
| + pending_swap_ack_count_++; |
| + } |
| + |
| + void OnSwapBuffersComplete() override { pending_swap_ack_count_--; } |
| + |
| + void ReclaimResourcesOnCompositorThread( |
| + const cc::ReturnedResourceArray& resources) override { |
| + unclaimed_resources_count_--; |
| + } |
| + |
| + int pending_swap_ack_count() const { return pending_swap_ack_count_; } |
| + int unclaimed_resources_count() const { return unclaimed_resources_count_; } |
| + |
| + private: |
| + int pending_swap_ack_count_; |
| + int unclaimed_resources_count_; |
| +}; |
| + |
| +class DelegatedOutputSurfaceTest : public testing::Test { |
| + public: |
| + DelegatedOutputSurfaceTest() {} |
| + |
| + void SetUpTest(bool bind_should_fail) { |
| + main_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| + compositor_thread_ = base::MakeUnique<base::Thread>("Compositor"); |
| + ASSERT_TRUE(compositor_thread_->Start()); |
| + compositor_task_runner_ = compositor_thread_->task_runner(); |
| + output_surface_ = base::MakeUnique<TestDelegatedOutputSurface>( |
| + TestContextProvider::Create(bind_should_fail), nullptr, |
| + main_task_runner_, compositor_task_runner_, |
| + &blimp_output_surface_client_); |
| + |
| + base::WaitableEvent init_event( |
| + base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| + base::WaitableEvent::InitialState::NOT_SIGNALED); |
| + compositor_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&DelegatedOutputSurfaceTest::InitOnCompositorThread, |
| + base::Unretained(this), &init_event)); |
| + init_event.Wait(); |
| + BeginTest(); |
| + base::MessageLoop::current()->RunUntilIdle(); |
| + } |
| + |
| + virtual void BeginTest() = 0; |
| + |
| + void DoSwapBuffers() { |
| + compositor_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&DelegatedOutputSurfaceTest::DoSwapBuffersOnCompositorThread, |
| + base::Unretained(this))); |
| + } |
| + |
| + void TearDown() override { |
| + EXPECT_EQ(blimp_output_surface_client_.swap_count(), |
| + output_surface_client_.swap_count()); |
| + } |
| + |
| + void EndTest() { |
| + base::WaitableEvent shutdown_event( |
| + base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| + base::WaitableEvent::InitialState::NOT_SIGNALED); |
| + compositor_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&DelegatedOutputSurfaceTest::ShutdownOnCompositorThread, |
| + base::Unretained(this), &shutdown_event)); |
| + shutdown_event.Wait(); |
| + compositor_thread_->Stop(); |
| + } |
| + |
| + void InitOnCompositorThread(base::WaitableEvent* event) { |
| + bound_ = output_surface_->BindToClient(&output_surface_client_); |
| + event->Signal(); |
| + } |
| + |
| + void DoSwapBuffersOnCompositorThread() { |
| + output_surface_->SwapBuffers(cc::CompositorFrame()); |
| + } |
| + |
| + void ShutdownOnCompositorThread(base::WaitableEvent* event) { |
| + EXPECT_EQ(0, output_surface_->unclaimed_resources_count()); |
| + EXPECT_EQ(0, output_surface_->pending_swap_ack_count()); |
| + if (bound_) { |
| + output_surface_->DetachFromClient(); |
| + bound_ = false; |
| + } |
| + event->Signal(); |
| + } |
| + |
| + base::MessageLoop loop_; |
| + std::unique_ptr<base::Thread> compositor_thread_; |
| + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
| + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; |
| + std::unique_ptr<TestDelegatedOutputSurface> output_surface_; |
| + FakeBlimpOutputSurfaceClient blimp_output_surface_client_; |
| + |
| + bool bound_ = false; |
| + cc::FakeOutputSurfaceClient output_surface_client_; |
| +}; |
| + |
| +class DelegatedOutputSurfaceTestBindFails : public DelegatedOutputSurfaceTest { |
| + void SetUp() override { SetUpTest(true); } |
| + |
| + void BeginTest() override { |
| + // Do nothing. We'll just check the surfaces count on tear down to make sure |
| + // there were no registrations. |
| + EndTest(); |
| + } |
| + |
| + void TearDown() override { |
| + DelegatedOutputSurfaceTest::TearDown(); |
| + EXPECT_EQ(0, blimp_output_surface_client_.surfaces_bound()); |
| + } |
| +}; |
| + |
| +TEST_F(DelegatedOutputSurfaceTestBindFails, NoRegistrations) {} |
|
David Trainor- moved to gerrit
2016/08/24 23:09:34
Can we put the test flow in here?
SetupTest(true/
Khushal
2016/08/25 02:35:39
Done.
|
| + |
| +class DelegatedOutputSurfaceTestBindSucceeds |
| + : public DelegatedOutputSurfaceTest { |
| + void SetUp() override { SetUpTest(false); } |
| + |
| + void BeginTest() override { |
| + DoSwapBuffers(); |
| + DoSwapBuffers(); |
| + DoSwapBuffers(); |
| + } |
| + |
| + void TearDown() override { |
| + DelegatedOutputSurfaceTest::TearDown(); |
| + EXPECT_EQ(3, blimp_output_surface_client_.swap_count()); |
| + } |
| +}; |
| + |
| +TEST_F(DelegatedOutputSurfaceTestBindSucceeds, SwapBuffers) {} |
|
David Trainor- moved to gerrit
2016/08/24 23:09:34
Who calls EndTest? Could we just put most of this
Khushal
2016/08/25 02:35:39
Done.
|
| + |
| +} // namespace |
| +} // namespace client |
| +} // namespace blimp |