Fix flaky PDFExtensionTest
[chromium-blink-merge.git] / cc / layers / delegated_frame_resource_collection_unittest.cc
blobe5426a0e01a355378ce8f6e4b1a2fa37a9a489bf
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.
5 #include "base/bind.h"
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"
18 namespace cc {
19 namespace {
21 class DelegatedFrameResourceCollectionTest
22 : public testing::Test,
23 public DelegatedFrameResourceCollectionClient {
24 protected:
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;
47 resource.id = 444;
48 resources.push_back(resource);
49 return resources;
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;
63 return r;
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);
90 if (event)
91 event->Wait();
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");
99 thread.Start();
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(
117 FROM_HERE,
118 base::Bind(
119 &ReturnResourcesOnThread,
120 resource_collection_->GetReturnResourcesCallbackForImplThread(),
121 returned_resources, &event, main_thread_task_runner.get()));
123 run_loop.Run();
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();
136 event.Signal();
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(
157 FROM_HERE,
158 base::Bind(&ReturnResourcesOnThread, return_callback, returned_resources,
159 null_event, main_thread_task_runner.get()));
161 thread.Stop();
164 } // namespace
165 } // namespace cc