OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "base/bind.h" | |
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" | |
14 | |
15 namespace cc { | |
16 namespace { | |
17 | |
18 class DelegatedFrameResourceCollectionTest | |
19 : public testing::Test, | |
20 public DelegatedFrameResourceCollectionClient { | |
21 protected: | |
22 DelegatedFrameResourceCollectionTest() : resources_available_(false) {} | |
23 | |
24 void SetUp() override { CreateResourceCollection(); } | |
25 | |
26 void TearDown() override { DestroyResourceCollection(); } | |
27 | |
28 void CreateResourceCollection() { | |
29 DCHECK(!resource_collection_.get()); | |
30 resource_collection_ = new DelegatedFrameResourceCollection; | |
31 resource_collection_->SetClient(this); | |
32 } | |
33 | |
34 void DestroyResourceCollection() { | |
35 if (resource_collection_.get()) { | |
36 resource_collection_->SetClient(nullptr); | |
37 resource_collection_ = nullptr; | |
38 } | |
39 } | |
40 | |
41 TransferableResourceArray CreateResourceArray() { | |
42 TransferableResourceArray resources; | |
43 TransferableResource resource; | |
44 resource.id = 444; | |
45 resources.push_back(resource); | |
46 return resources; | |
47 } | |
48 | |
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(); | |
55 } | |
56 | |
57 bool ReturnAndResetResourcesAvailable() { | |
58 bool r = resources_available_; | |
59 resources_available_ = false; | |
60 return r; | |
61 } | |
62 | |
63 scoped_refptr<DelegatedFrameResourceCollection> resource_collection_; | |
64 bool resources_available_; | |
65 ReturnedResourceArray returned_resources_; | |
66 base::Closure resources_available_closure_; | |
67 }; | |
68 | |
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()); | |
74 | |
75 ReturnCallback return_callback = | |
76 resource_collection_->GetReturnResourcesCallbackForImplThread(); | |
77 | |
78 // Callback shouldn't take a ref since it's sent to other threads. | |
79 EXPECT_TRUE(resource_collection_->HasOneRef()); | |
80 } | |
81 | |
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); | |
87 if (event) | |
88 event->Wait(); | |
89 } | |
90 | |
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"); | |
96 thread.Start(); | |
97 scoped_ptr<BlockingTaskRunner> main_thread_task_runner( | |
98 BlockingTaskRunner::Create(base::MessageLoopProxy::current())); | |
99 | |
100 TransferableResourceArray resources = CreateResourceArray(); | |
101 resource_collection_->ReceivedResources(resources); | |
102 resource_collection_->RefResources(resources); | |
103 | |
104 ReturnedResourceArray returned_resources; | |
105 TransferableResource::ReturnResources(resources, &returned_resources); | |
106 | |
107 base::WaitableEvent event(false, false); | |
108 | |
109 { | |
110 base::RunLoop run_loop; | |
111 resources_available_closure_ = run_loop.QuitClosure(); | |
112 | |
113 thread.message_loop()->PostTask( | |
114 FROM_HERE, | |
115 base::Bind( | |
116 &ReturnResourcesOnThread, | |
117 resource_collection_->GetReturnResourcesCallbackForImplThread(), | |
118 returned_resources, | |
119 &event, | |
120 main_thread_task_runner.get())); | |
121 | |
122 run_loop.Run(); | |
123 } | |
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(); | |
129 | |
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(); | |
135 event.Signal(); | |
136 | |
137 CreateResourceCollection(); | |
138 resource_collection_->ReceivedResources(resources); | |
139 resource_collection_->RefResources(resources); | |
140 | |
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(); | |
146 | |
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(); | |
153 | |
154 base::WaitableEvent* null_event = nullptr; | |
155 thread.message_loop()->PostTask(FROM_HERE, | |
156 base::Bind(&ReturnResourcesOnThread, | |
157 return_callback, | |
158 returned_resources, | |
159 null_event, | |
160 main_thread_task_runner.get())); | |
161 | |
162 thread.Stop(); | |
163 } | |
164 | |
165 } // namespace | |
166 } // namespace cc | |
OLD | NEW |