Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / cc / layers / delegated_frame_resource_collection_unittest.cc
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   virtual void SetUp() OVERRIDE { CreateResourceCollection(); }
25
26   virtual 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(NULL);
37       resource_collection_ = NULL;
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   virtual 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 = NULL;
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