1 // Copyright 2013 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.
6 #include "base/location.h"
7 #include "base/run_loop.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/threading/thread.h"
12 #include "cc/layers/delegated_frame_resource_collection.h"
13 #include "cc/resources/returned_resource.h"
14 #include "cc/resources/transferable_resource.h"
15 #include "cc/trees/blocking_task_runner.h"
16 #include "testing/gtest/include/gtest/gtest.h"
21 class DelegatedFrameResourceCollectionTest
22 : public testing::Test
,
23 public DelegatedFrameResourceCollectionClient
{
25 DelegatedFrameResourceCollectionTest() : resources_available_(false) {}
27 void SetUp() override
{ CreateResourceCollection(); }
29 void TearDown() override
{ DestroyResourceCollection(); }
31 void CreateResourceCollection() {
32 DCHECK(!resource_collection_
.get());
33 resource_collection_
= new DelegatedFrameResourceCollection
;
34 resource_collection_
->SetClient(this);
37 void DestroyResourceCollection() {
38 if (resource_collection_
.get()) {
39 resource_collection_
->SetClient(nullptr);
40 resource_collection_
= nullptr;
44 TransferableResourceArray
CreateResourceArray() {
45 TransferableResourceArray resources
;
46 TransferableResource resource
;
48 resources
.push_back(resource
);
52 void UnusedResourcesAreAvailable() override
{
53 resources_available_
= true;
54 resource_collection_
->TakeUnusedResourcesForChildCompositor(
55 &returned_resources_
);
56 if (!resources_available_closure_
.is_null())
57 resources_available_closure_
.Run();
60 bool ReturnAndResetResourcesAvailable() {
61 bool r
= resources_available_
;
62 resources_available_
= false;
66 scoped_refptr
<DelegatedFrameResourceCollection
> resource_collection_
;
67 bool resources_available_
;
68 ReturnedResourceArray returned_resources_
;
69 base::Closure resources_available_closure_
;
72 // This checks that taking the return callback doesn't take extra refcounts,
73 // since it's sent to other threads.
74 TEST_F(DelegatedFrameResourceCollectionTest
, NoRef
) {
75 // Start with one ref.
76 EXPECT_TRUE(resource_collection_
->HasOneRef());
78 ReturnCallback return_callback
=
79 resource_collection_
->GetReturnResourcesCallbackForImplThread();
81 // Callback shouldn't take a ref since it's sent to other threads.
82 EXPECT_TRUE(resource_collection_
->HasOneRef());
85 void ReturnResourcesOnThread(ReturnCallback callback
,
86 const ReturnedResourceArray
& resources
,
87 base::WaitableEvent
* event
,
88 BlockingTaskRunner
* main_thread_task_runner
) {
89 callback
.Run(resources
, main_thread_task_runner
);
94 // Tests that the ReturnCallback can run safely on threads even after the
95 // last references to the collection were dropped.
96 // Flaky: crbug.com/313441
97 TEST_F(DelegatedFrameResourceCollectionTest
, Thread
) {
98 base::Thread
thread("test thread");
100 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner(
101 BlockingTaskRunner::Create(base::ThreadTaskRunnerHandle::Get()));
103 TransferableResourceArray resources
= CreateResourceArray();
104 resource_collection_
->ReceivedResources(resources
);
105 resource_collection_
->RefResources(resources
);
107 ReturnedResourceArray returned_resources
;
108 TransferableResource::ReturnResources(resources
, &returned_resources
);
110 base::WaitableEvent
event(false, false);
113 base::RunLoop run_loop
;
114 resources_available_closure_
= run_loop
.QuitClosure();
116 thread
.message_loop()->task_runner()->PostTask(
119 &ReturnResourcesOnThread
,
120 resource_collection_
->GetReturnResourcesCallbackForImplThread(),
121 returned_resources
, &event
, main_thread_task_runner
.get()));
125 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
126 EXPECT_EQ(1u, returned_resources_
.size());
127 EXPECT_EQ(444u, returned_resources_
[0].id
);
128 EXPECT_EQ(1, returned_resources_
[0].count
);
129 returned_resources_
.clear();
131 // The event prevents the return resources callback from being deleted.
132 // Destroy the last reference from this thread to the collection before
133 // signaling the event, to ensure any reference taken by the callback, if any,
134 // would be the last one.
135 DestroyResourceCollection();
138 CreateResourceCollection();
139 resource_collection_
->ReceivedResources(resources
);
140 resource_collection_
->RefResources(resources
);
142 // Destroy the collection before we have a chance to run the return callback.
143 ReturnCallback return_callback
=
144 resource_collection_
->GetReturnResourcesCallbackForImplThread();
145 resource_collection_
->LoseAllResources();
146 DestroyResourceCollection();
148 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
149 EXPECT_EQ(1u, returned_resources_
.size());
150 EXPECT_EQ(444u, returned_resources_
[0].id
);
151 EXPECT_EQ(1, returned_resources_
[0].count
);
152 EXPECT_TRUE(returned_resources_
[0].lost
);
153 returned_resources_
.clear();
155 base::WaitableEvent
* null_event
= nullptr;
156 thread
.message_loop()->task_runner()->PostTask(
158 base::Bind(&ReturnResourcesOnThread
, return_callback
, returned_resources
,
159 null_event
, main_thread_task_runner
.get()));