- add sources.
[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 "testing/gtest/include/gtest/gtest.h"
13
14 namespace cc {
15 namespace {
16
17 class 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.
70 TEST_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
81 void ReturnResourcesOnThread(ReturnCallback callback,
82                              const ReturnedResourceArray& resources,
83                              base::WaitableEvent* event) {
84   callback.Run(resources);
85   if (event)
86     event->Wait();
87 }
88
89 // Tests that the ReturnCallback can run safely on threads even after the
90 // last references to the collection were dropped.
91 // Flaky: crbug.com/313441
92 TEST_F(DelegatedFrameResourceCollectionTest, Thread) {
93   base::Thread thread("test thread");
94   thread.Start();
95
96   TransferableResourceArray resources = CreateResourceArray();
97   resource_collection_->ReceivedResources(resources);
98   resource_collection_->RefResources(resources);
99
100   ReturnedResourceArray returned_resources;
101   TransferableResource::ReturnResources(resources, &returned_resources);
102
103   base::WaitableEvent event(false, false);
104
105   {
106     base::RunLoop run_loop;
107     resources_available_closure_ = run_loop.QuitClosure();
108
109     thread.message_loop()->PostTask(
110         FROM_HERE,
111         base::Bind(
112             &ReturnResourcesOnThread,
113             resource_collection_->GetReturnResourcesCallbackForImplThread(),
114             returned_resources,
115             &event));
116
117     run_loop.Run();
118   }
119   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
120   EXPECT_EQ(1u, returned_resources_.size());
121   EXPECT_EQ(444u, returned_resources_[0].id);
122   EXPECT_EQ(1, returned_resources_[0].count);
123   returned_resources_.clear();
124
125   // The event prevents the return resources callback from being deleted.
126   // Destroy the last reference from this thread to the collection before
127   // signaling the event, to ensure any reference taken by the callback, if any,
128   // would be the last one.
129   DestroyResourceCollection();
130   event.Signal();
131
132   CreateResourceCollection();
133   resource_collection_->ReceivedResources(resources);
134   resource_collection_->RefResources(resources);
135
136   // Destroy the collection before we have a chance to run the return callback.
137   ReturnCallback return_callback =
138       resource_collection_->GetReturnResourcesCallbackForImplThread();
139   resource_collection_->LoseAllResources();
140   DestroyResourceCollection();
141
142   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
143   EXPECT_EQ(1u, returned_resources_.size());
144   EXPECT_EQ(444u, returned_resources_[0].id);
145   EXPECT_EQ(1, returned_resources_[0].count);
146   EXPECT_TRUE(returned_resources_[0].lost);
147   returned_resources_.clear();
148
149   base::WaitableEvent* null_event = NULL;
150   thread.message_loop()->PostTask(FROM_HERE,
151                                   base::Bind(&ReturnResourcesOnThread,
152                                              return_callback,
153                                              returned_resources,
154                                              null_event));
155
156   thread.Stop();
157 }
158
159 }  // namespace
160 }  // namespace cc