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) {}
28 void TestCallback_0() { ++called_num
; }
30 void TestCallback_1(int p1
) { ++called_num
; }
32 void TestCallback_2(int p1
, const double* p2
) { ++called_num
; }
34 void TestCallback_3(int p1
, const double* p2
, bool* p3
) { ++called_num
; }
36 void TestCallback_4(int p1
, const double* p2
, bool* p3
, TestParameter p4
) {
40 void TestCallback_5(int p1
,
44 const TestParameter
& p5
) {
48 typedef proxy::PluginProxyTest ThreadAwareCallbackTest
;
50 // Test that a callback created on the main thread will run on the main thread,
51 // even when requested from a different thread.
52 class ThreadAwareCallbackMultiThreadTest
53 : public proxy::PluginProxyMultiThreadTest
{
55 ThreadAwareCallbackMultiThreadTest() : main_thread_callback_called_(false) {}
56 virtual ~ThreadAwareCallbackMultiThreadTest() {
57 CHECK(main_thread_callback_called_
);
60 // proxy::PluginProxyMultiThreadTest implementation.
61 virtual void SetUpTestOnMainThread() OVERRIDE
{
62 ProxyAutoLock auto_lock
;
64 main_thread_callback_
.reset(
65 ThreadAwareCallback
<CallbackFunc
>::Create(&MainThreadCallbackBody
));
68 virtual void SetUpTestOnSecondaryThread() OVERRIDE
{
70 ProxyAutoLock auto_lock
;
71 main_thread_callback_
->RunOnTargetThread(this);
74 PostQuitForSecondaryThread();
75 PostQuitForMainThread();
79 typedef void (*CallbackFunc
)(ThreadAwareCallbackMultiThreadTest
*);
81 static void MainThreadCallbackBody(ThreadAwareCallbackMultiThreadTest
* thiz
) {
82 thiz
->CheckOnThread(MAIN_THREAD
);
83 thiz
->main_thread_callback_called_
= true;
86 ProxyAutoLock auto_lock
;
87 // We have to destroy it prior to the PluginGlobals instance held by the
88 // base class. Otherwise it has a ref to Pepper message loop for the main
89 // thread and the PluginGlobals destructor will complain.
90 thiz
->main_thread_callback_
.reset(NULL
);
94 scoped_ptr
<ThreadAwareCallback
<CallbackFunc
> > main_thread_callback_
;
95 bool main_thread_callback_called_
;
98 // Test that when a ThreadAwareCallback instance is destroyed, pending tasks to
99 // run the callback will be ignored.
100 class ThreadAwareCallbackAbortTest
: public proxy::PluginProxyMultiThreadTest
{
102 ThreadAwareCallbackAbortTest() {}
103 virtual ~ThreadAwareCallbackAbortTest() {}
105 // proxy::PluginProxyMultiThreadTest implementation.
106 virtual void SetUpTestOnMainThread() OVERRIDE
{
107 ProxyAutoLock auto_lock
;
109 main_thread_callback_
.reset(
110 ThreadAwareCallback
<CallbackFunc
>::Create(&MainThreadCallbackBody
));
113 virtual void SetUpTestOnSecondaryThread() OVERRIDE
{
115 ProxyAutoLock auto_lock
;
116 main_thread_message_loop_proxy_
->PostTask(
118 base::Bind(&ThreadAwareCallbackAbortTest::DeleteCallback
,
119 base::Unretained(this)));
120 // |main_thread_callback_| is still valid, even if DeleteCallback() can be
121 // called before this following statement. That is because |auto_lock| is
122 // still held by this method, which prevents DeleteCallback() from
123 // deleting the callback.
124 main_thread_callback_
->RunOnTargetThread(this);
127 PostQuitForSecondaryThread();
128 PostQuitForMainThread();
132 typedef void (*CallbackFunc
)(ThreadAwareCallbackAbortTest
*);
134 static void MainThreadCallbackBody(ThreadAwareCallbackAbortTest
* thiz
) {
135 // The callback should not be called.
139 void DeleteCallback() {
140 ProxyAutoLock auto_lock
;
141 main_thread_callback_
.reset(NULL
);
144 scoped_ptr
<ThreadAwareCallback
<CallbackFunc
> > main_thread_callback_
;
149 TEST_F(ThreadAwareCallbackTest
, Basics
) {
150 // ThreadAwareCallback should only be used when the proxy lock has been
152 ProxyAutoLock auto_lock
;
154 double double_arg
= 0.0;
155 bool bool_arg
= false;
156 TestParameter object_arg
;
158 // Exercise all the template code.
160 typedef void (*FuncType_0
)();
161 scoped_ptr
<ThreadAwareCallback
<FuncType_0
> > callback_0(
162 ThreadAwareCallback
<FuncType_0
>::Create(TestCallback_0
));
163 callback_0
->RunOnTargetThread();
165 typedef void (*FuncType_1
)(int);
166 scoped_ptr
<ThreadAwareCallback
<FuncType_1
> > callback_1(
167 ThreadAwareCallback
<FuncType_1
>::Create(TestCallback_1
));
168 callback_1
->RunOnTargetThread(1);
170 typedef void (*FuncType_2
)(int, const double*);
171 scoped_ptr
<ThreadAwareCallback
<FuncType_2
> > callback_2(
172 ThreadAwareCallback
<FuncType_2
>::Create(TestCallback_2
));
173 callback_2
->RunOnTargetThread(1, &double_arg
);
175 typedef void (*FuncType_3
)(int, const double*, bool*);
176 scoped_ptr
<ThreadAwareCallback
<FuncType_3
> > callback_3(
177 ThreadAwareCallback
<FuncType_3
>::Create(TestCallback_3
));
178 callback_3
->RunOnTargetThread(1, &double_arg
, &bool_arg
);
180 typedef void (*FuncType_4
)(int, const double*, bool*, TestParameter
);
181 scoped_ptr
<ThreadAwareCallback
<FuncType_4
> > callback_4(
182 ThreadAwareCallback
<FuncType_4
>::Create(TestCallback_4
));
183 callback_4
->RunOnTargetThread(1, &double_arg
, &bool_arg
, object_arg
);
185 typedef void (*FuncType_5
)(
186 int, const double*, bool*, TestParameter
, const TestParameter
&);
187 scoped_ptr
<ThreadAwareCallback
<FuncType_5
> > callback_5(
188 ThreadAwareCallback
<FuncType_5
>::Create(TestCallback_5
));
189 callback_5
->RunOnTargetThread(
190 1, &double_arg
, &bool_arg
, object_arg
, object_arg
);
192 EXPECT_EQ(6, called_num
);
195 TEST_F(ThreadAwareCallbackMultiThreadTest
, RunOnTargetThread
) { RunTest(); }
197 TEST_F(ThreadAwareCallbackAbortTest
, NotRunIfAborted
) { RunTest(); }