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/run_loop.h"
7 #include "base/synchronization/waitable_event.h"
8 #include "base/threading/thread.h"
9 #include "cc/layers/delegated_frame_resource_collection.h"
10 #include "cc/resources/returned_resource.h"
11 #include "cc/resources/transferable_resource.h"
12 #include "cc/trees/blocking_task_runner.h"
13 #include "testing/gtest/include/gtest/gtest.h"
18 class DelegatedFrameResourceCollectionTest
19 : public testing::Test
,
20 public DelegatedFrameResourceCollectionClient
{
22 DelegatedFrameResourceCollectionTest() : resources_available_(false) {}
24 void SetUp() override
{ CreateResourceCollection(); }
26 void TearDown() override
{ DestroyResourceCollection(); }
28 void CreateResourceCollection() {
29 DCHECK(!resource_collection_
.get());
30 resource_collection_
= new DelegatedFrameResourceCollection
;
31 resource_collection_
->SetClient(this);
34 void DestroyResourceCollection() {
35 if (resource_collection_
.get()) {
36 resource_collection_
->SetClient(nullptr);
37 resource_collection_
= nullptr;
41 TransferableResourceArray
CreateResourceArray() {
42 TransferableResourceArray resources
;
43 TransferableResource resource
;
45 resources
.push_back(resource
);
49 void UnusedResourcesAreAvailable() override
{
50 resources_available_
= true;
51 resource_collection_
->TakeUnusedResourcesForChildCompositor(
52 &returned_resources_
);
53 if (!resources_available_closure_
.is_null())
54 resources_available_closure_
.Run();
57 bool ReturnAndResetResourcesAvailable() {
58 bool r
= resources_available_
;
59 resources_available_
= false;
63 scoped_refptr
<DelegatedFrameResourceCollection
> resource_collection_
;
64 bool resources_available_
;
65 ReturnedResourceArray returned_resources_
;
66 base::Closure resources_available_closure_
;
69 // This checks that taking the return callback doesn't take extra refcounts,
70 // since it's sent to other threads.
71 TEST_F(DelegatedFrameResourceCollectionTest
, NoRef
) {
72 // Start with one ref.
73 EXPECT_TRUE(resource_collection_
->HasOneRef());
75 ReturnCallback return_callback
=
76 resource_collection_
->GetReturnResourcesCallbackForImplThread();
78 // Callback shouldn't take a ref since it's sent to other threads.
79 EXPECT_TRUE(resource_collection_
->HasOneRef());
82 void ReturnResourcesOnThread(ReturnCallback callback
,
83 const ReturnedResourceArray
& resources
,
84 base::WaitableEvent
* event
,
85 BlockingTaskRunner
* main_thread_task_runner
) {
86 callback
.Run(resources
, main_thread_task_runner
);
91 // Tests that the ReturnCallback can run safely on threads even after the
92 // last references to the collection were dropped.
93 // Flaky: crbug.com/313441
94 TEST_F(DelegatedFrameResourceCollectionTest
, Thread
) {
95 base::Thread
thread("test thread");
97 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner(
98 BlockingTaskRunner::Create(base::MessageLoopProxy::current()));
100 TransferableResourceArray resources
= CreateResourceArray();
101 resource_collection_
->ReceivedResources(resources
);
102 resource_collection_
->RefResources(resources
);
104 ReturnedResourceArray returned_resources
;
105 TransferableResource::ReturnResources(resources
, &returned_resources
);
107 base::WaitableEvent
event(false, false);
110 base::RunLoop run_loop
;
111 resources_available_closure_
= run_loop
.QuitClosure();
113 thread
.message_loop()->PostTask(
116 &ReturnResourcesOnThread
,
117 resource_collection_
->GetReturnResourcesCallbackForImplThread(),
120 main_thread_task_runner
.get()));
124 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
125 EXPECT_EQ(1u, returned_resources_
.size());
126 EXPECT_EQ(444u, returned_resources_
[0].id
);
127 EXPECT_EQ(1, returned_resources_
[0].count
);
128 returned_resources_
.clear();
130 // The event prevents the return resources callback from being deleted.
131 // Destroy the last reference from this thread to the collection before
132 // signaling the event, to ensure any reference taken by the callback, if any,
133 // would be the last one.
134 DestroyResourceCollection();
137 CreateResourceCollection();
138 resource_collection_
->ReceivedResources(resources
);
139 resource_collection_
->RefResources(resources
);
141 // Destroy the collection before we have a chance to run the return callback.
142 ReturnCallback return_callback
=
143 resource_collection_
->GetReturnResourcesCallbackForImplThread();
144 resource_collection_
->LoseAllResources();
145 DestroyResourceCollection();
147 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
148 EXPECT_EQ(1u, returned_resources_
.size());
149 EXPECT_EQ(444u, returned_resources_
[0].id
);
150 EXPECT_EQ(1, returned_resources_
[0].count
);
151 EXPECT_TRUE(returned_resources_
[0].lost
);
152 returned_resources_
.clear();
154 base::WaitableEvent
* null_event
= nullptr;
155 thread
.message_loop()->PostTask(FROM_HERE
,
156 base::Bind(&ReturnResourcesOnThread
,
160 main_thread_task_runner
.get()));