1 // Copyright (c) 2012 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 "ppapi/shared_impl/thread_aware_callback.h"
7 #include "base/bind_helpers.h"
8 #include "base/compiler_specific.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "ppapi/c/pp_errors.h"
12 #include "ppapi/proxy/ppapi_proxy_test.h"
13 #include "testing/gtest/include/gtest/gtest.h"
21 TestParameter() : value_(0) {
29 void TestCallback_0() {
33 void TestCallback_1(int p1
) {
37 void TestCallback_2(int p1
, const double* p2
) {
41 void TestCallback_3(int p1
, const double* p2
, bool* p3
) {
45 void TestCallback_4(int p1
, const double* p2
, bool* p3
, TestParameter p4
) {
49 void TestCallback_5(int p1
,
53 const TestParameter
& p5
) {
57 typedef proxy::PluginProxyTest ThreadAwareCallbackTest
;
59 // Test that a callback created on the main thread will run on the main thread,
60 // even when requested from a different thread.
61 class ThreadAwareCallbackMultiThreadTest
62 : public proxy::PluginProxyMultiThreadTest
{
64 ThreadAwareCallbackMultiThreadTest() : main_thread_callback_called_(false) {
66 virtual ~ThreadAwareCallbackMultiThreadTest() {
67 CHECK(main_thread_callback_called_
);
70 // proxy::PluginProxyMultiThreadTest implementation.
71 virtual void SetUpTestOnMainThread() OVERRIDE
{
72 ProxyAutoLock auto_lock
;
74 main_thread_callback_
.reset(
75 ThreadAwareCallback
<CallbackFunc
>::Create(&MainThreadCallbackBody
));
78 virtual void SetUpTestOnSecondaryThread() OVERRIDE
{
80 ProxyAutoLock auto_lock
;
81 main_thread_callback_
->RunOnTargetThread(this);
84 PostQuitForSecondaryThread();
85 PostQuitForMainThread();
89 typedef void (*CallbackFunc
)(ThreadAwareCallbackMultiThreadTest
*);
91 static void MainThreadCallbackBody(ThreadAwareCallbackMultiThreadTest
* thiz
) {
92 thiz
->CheckOnThread(MAIN_THREAD
);
93 thiz
->main_thread_callback_called_
= true;
96 ProxyAutoLock auto_lock
;
97 // We have to destroy it prior to the PluginGlobals instance held by the
98 // base class. Otherwise it has a ref to Pepper message loop for the main
99 // thread and the PluginGlobals destructor will complain.
100 thiz
->main_thread_callback_
.reset(NULL
);
104 scoped_ptr
<ThreadAwareCallback
<CallbackFunc
> > main_thread_callback_
;
105 bool main_thread_callback_called_
;
108 // Test that when a ThreadAwareCallback instance is destroyed, pending tasks to
109 // run the callback will be ignored.
110 class ThreadAwareCallbackAbortTest
: public proxy::PluginProxyMultiThreadTest
{
112 ThreadAwareCallbackAbortTest() {
114 virtual ~ThreadAwareCallbackAbortTest() {
117 // proxy::PluginProxyMultiThreadTest implementation.
118 virtual void SetUpTestOnMainThread() OVERRIDE
{
119 ProxyAutoLock auto_lock
;
121 main_thread_callback_
.reset(
122 ThreadAwareCallback
<CallbackFunc
>::Create(&MainThreadCallbackBody
));
125 virtual void SetUpTestOnSecondaryThread() OVERRIDE
{
127 ProxyAutoLock auto_lock
;
128 main_thread_message_loop_proxy_
->PostTask(
130 base::Bind(&ThreadAwareCallbackAbortTest::DeleteCallback
,
131 base::Unretained(this)));
132 // |main_thread_callback_| is still valid, even if DeleteCallback() can be
133 // called before this following statement. That is because |auto_lock| is
134 // still held by this method, which prevents DeleteCallback() from
135 // deleting the callback.
136 main_thread_callback_
->RunOnTargetThread(this);
139 PostQuitForSecondaryThread();
140 PostQuitForMainThread();
144 typedef void (*CallbackFunc
)(ThreadAwareCallbackAbortTest
*);
146 static void MainThreadCallbackBody(ThreadAwareCallbackAbortTest
* thiz
) {
147 // The callback should not be called.
151 void DeleteCallback() {
152 ProxyAutoLock auto_lock
;
153 main_thread_callback_
.reset(NULL
);
156 scoped_ptr
<ThreadAwareCallback
<CallbackFunc
> > main_thread_callback_
;
161 TEST_F(ThreadAwareCallbackTest
, Basics
) {
162 // ThreadAwareCallback should only be used when the proxy lock has been
164 ProxyAutoLock auto_lock
;
166 double double_arg
= 0.0;
167 bool bool_arg
= false;
168 TestParameter object_arg
;
170 // Exercise all the template code.
172 typedef void (*FuncType_0
)();
173 scoped_ptr
<ThreadAwareCallback
<FuncType_0
> > callback_0(
174 ThreadAwareCallback
<FuncType_0
>::Create(TestCallback_0
));
175 callback_0
->RunOnTargetThread();
177 typedef void (*FuncType_1
)(int);
178 scoped_ptr
<ThreadAwareCallback
<FuncType_1
> > callback_1(
179 ThreadAwareCallback
<FuncType_1
>::Create(TestCallback_1
));
180 callback_1
->RunOnTargetThread(1);
182 typedef void (*FuncType_2
)(int, const double*);
183 scoped_ptr
<ThreadAwareCallback
<FuncType_2
> > callback_2(
184 ThreadAwareCallback
<FuncType_2
>::Create(TestCallback_2
));
185 callback_2
->RunOnTargetThread(1, &double_arg
);
187 typedef void (*FuncType_3
)(int, const double*, bool*);
188 scoped_ptr
<ThreadAwareCallback
<FuncType_3
> > callback_3(
189 ThreadAwareCallback
<FuncType_3
>::Create(TestCallback_3
));
190 callback_3
->RunOnTargetThread(1, &double_arg
, &bool_arg
);
192 typedef void (*FuncType_4
)(int, const double*, bool*, TestParameter
);
193 scoped_ptr
<ThreadAwareCallback
<FuncType_4
> > callback_4(
194 ThreadAwareCallback
<FuncType_4
>::Create(TestCallback_4
));
195 callback_4
->RunOnTargetThread(1, &double_arg
, &bool_arg
, object_arg
);
197 typedef void (*FuncType_5
)(int,
201 const TestParameter
&);
202 scoped_ptr
<ThreadAwareCallback
<FuncType_5
> > callback_5(
203 ThreadAwareCallback
<FuncType_5
>::Create(TestCallback_5
));
204 callback_5
->RunOnTargetThread(1, &double_arg
, &bool_arg
, object_arg
,
207 EXPECT_EQ(6, called_num
);
210 TEST_F(ThreadAwareCallbackMultiThreadTest
, RunOnTargetThread
) {
214 TEST_F(ThreadAwareCallbackAbortTest
, NotRunIfAborted
) {