delegated_frame_resource_collection_unittest.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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 "testing/gtest/include/gtest/gtest.h" 13 14namespace cc { 15namespace { 16 17class DelegatedFrameResourceCollectionTest 18 : public testing::Test, 19 public DelegatedFrameResourceCollectionClient { 20 protected: 21 DelegatedFrameResourceCollectionTest() : resources_available_(false) {} 22 23 virtual void SetUp() OVERRIDE { CreateResourceCollection(); } 24 25 virtual void TearDown() OVERRIDE { DestroyResourceCollection(); } 26 27 void CreateResourceCollection() { 28 DCHECK(!resource_collection_); 29 resource_collection_ = new DelegatedFrameResourceCollection; 30 resource_collection_->SetClient(this); 31 } 32 33 void DestroyResourceCollection() { 34 if (resource_collection_) { 35 resource_collection_->SetClient(NULL); 36 resource_collection_ = NULL; 37 } 38 } 39 40 TransferableResourceArray CreateResourceArray() { 41 TransferableResourceArray resources; 42 TransferableResource resource; 43 resource.id = 444; 44 resources.push_back(resource); 45 return resources; 46 } 47 48 virtual void UnusedResourcesAreAvailable() OVERRIDE { 49 resources_available_ = true; 50 resource_collection_->TakeUnusedResourcesForChildCompositor( 51 &returned_resources_); 52 if (!resources_available_closure_.is_null()) 53 resources_available_closure_.Run(); 54 } 55 56 bool ReturnAndResetResourcesAvailable() { 57 bool r = resources_available_; 58 resources_available_ = false; 59 return r; 60 } 61 62 scoped_refptr<DelegatedFrameResourceCollection> resource_collection_; 63 bool resources_available_; 64 ReturnedResourceArray returned_resources_; 65 base::Closure resources_available_closure_; 66}; 67 68// This checks that taking the return callback doesn't take extra refcounts, 69// since it's sent to other threads. 70TEST_F(DelegatedFrameResourceCollectionTest, NoRef) { 71 // Start with one ref. 72 EXPECT_TRUE(resource_collection_->HasOneRef()); 73 74 ReturnCallback return_callback = 75 resource_collection_->GetReturnResourcesCallbackForImplThread(); 76 77 // Callback shouldn't take a ref since it's sent to other threads. 78 EXPECT_TRUE(resource_collection_->HasOneRef()); 79} 80 81void ReturnResourcesOnThread(ReturnCallback callback, 82 const ReturnedResourceArray& resources, 83 base::WaitableEvent* event) { 84 callback.Run(resources); 85 event->Wait(); 86} 87 88// Tests that the ReturnCallback can run safely on threads even after the 89// last references to the collection were dropped. 90// Flaky: crbug.com/313441 91TEST_F(DelegatedFrameResourceCollectionTest, DISABLED_Thread) { 92 base::Thread thread("test thread"); 93 thread.Start(); 94 95 TransferableResourceArray resources = CreateResourceArray(); 96 resource_collection_->ReceivedResources(resources); 97 resource_collection_->RefResources(resources); 98 99 ReturnedResourceArray returned_resources; 100 TransferableResource::ReturnResources(resources, &returned_resources); 101 102 base::WaitableEvent event(false, false); 103 104 { 105 base::RunLoop run_loop; 106 resources_available_closure_ = run_loop.QuitClosure(); 107 108 thread.message_loop()->PostTask( 109 FROM_HERE, 110 base::Bind( 111 &ReturnResourcesOnThread, 112 resource_collection_->GetReturnResourcesCallbackForImplThread(), 113 returned_resources, 114 &event)); 115 116 run_loop.Run(); 117 } 118 EXPECT_TRUE(ReturnAndResetResourcesAvailable()); 119 EXPECT_EQ(1u, returned_resources_.size()); 120 EXPECT_EQ(444u, returned_resources_[0].id); 121 EXPECT_EQ(1, returned_resources_[0].count); 122 returned_resources_.clear(); 123 124 // The event prevents the return resources callback from being deleted. 125 // Destroy the last reference from this thread to the collection before 126 // signaling the event, to ensure any reference taken by the callback, if any, 127 // would be the last one. 128 DestroyResourceCollection(); 129 event.Signal(); 130 131 CreateResourceCollection(); 132 resource_collection_->ReceivedResources(resources); 133 resource_collection_->RefResources(resources); 134 135 // Destroy the collection before we have a chance to run the return callback. 136 ReturnCallback return_callback = 137 resource_collection_->GetReturnResourcesCallbackForImplThread(); 138 resource_collection_->LoseAllResources(); 139 DestroyResourceCollection(); 140 141 EXPECT_TRUE(ReturnAndResetResourcesAvailable()); 142 EXPECT_EQ(1u, returned_resources_.size()); 143 EXPECT_EQ(444u, returned_resources_[0].id); 144 EXPECT_EQ(1, returned_resources_[0].count); 145 EXPECT_TRUE(returned_resources_[0].lost); 146 returned_resources_.clear(); 147 148 thread.message_loop()->PostTask(FROM_HERE, 149 base::Bind(&ReturnResourcesOnThread, 150 return_callback, 151 returned_resources, 152 &event)); 153 event.Signal(); 154 155 thread.Stop(); 156} 157 158} // namespace 159} // namespace cc 160