- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / shared_impl / thread_aware_callback_unittest.cc
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.
4
5 #include "ppapi/shared_impl/thread_aware_callback.h"
6
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"
14
15 namespace ppapi {
16
17 namespace {
18
19 class TestParameter {
20  public:
21   TestParameter() : value_(0) {
22   }
23
24   int value_;
25 };
26
27 int called_num = 0;
28
29 void TestCallback_0() {
30   ++called_num;
31 }
32
33 void TestCallback_1(int p1) {
34   ++called_num;
35 }
36
37 void TestCallback_2(int p1, const double* p2) {
38   ++called_num;
39 }
40
41 void TestCallback_3(int p1, const double* p2, bool* p3) {
42   ++called_num;
43 }
44
45 void TestCallback_4(int p1, const double* p2, bool* p3, TestParameter p4) {
46   ++called_num;
47 }
48
49 void TestCallback_5(int p1,
50                     const double* p2,
51                     bool* p3,
52                     TestParameter p4,
53                     const TestParameter& p5) {
54   ++called_num;
55 }
56
57 typedef proxy::PluginProxyTest ThreadAwareCallbackTest;
58
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 {
63  public:
64   ThreadAwareCallbackMultiThreadTest() : main_thread_callback_called_(false) {
65   }
66   virtual ~ThreadAwareCallbackMultiThreadTest() {
67     CHECK(main_thread_callback_called_);
68   }
69
70   // proxy::PluginProxyMultiThreadTest implementation.
71   virtual void SetUpTestOnMainThread() OVERRIDE {
72     ProxyAutoLock auto_lock;
73
74     main_thread_callback_.reset(
75         ThreadAwareCallback<CallbackFunc>::Create(&MainThreadCallbackBody));
76   }
77
78   virtual void SetUpTestOnSecondaryThread() OVERRIDE {
79     {
80       ProxyAutoLock auto_lock;
81       main_thread_callback_->RunOnTargetThread(this);
82     }
83
84     PostQuitForSecondaryThread();
85     PostQuitForMainThread();
86   }
87
88  private:
89   typedef void (*CallbackFunc)(ThreadAwareCallbackMultiThreadTest*);
90
91   static void MainThreadCallbackBody(ThreadAwareCallbackMultiThreadTest* thiz) {
92     thiz->CheckOnThread(MAIN_THREAD);
93     thiz->main_thread_callback_called_ = true;
94
95     {
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);
101     }
102   }
103
104   scoped_ptr<ThreadAwareCallback<CallbackFunc> > main_thread_callback_;
105   bool main_thread_callback_called_;
106 };
107
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 {
111  public:
112   ThreadAwareCallbackAbortTest() {
113   }
114   virtual ~ThreadAwareCallbackAbortTest() {
115   }
116
117   // proxy::PluginProxyMultiThreadTest implementation.
118   virtual void SetUpTestOnMainThread() OVERRIDE {
119     ProxyAutoLock auto_lock;
120
121     main_thread_callback_.reset(
122         ThreadAwareCallback<CallbackFunc>::Create(&MainThreadCallbackBody));
123   }
124
125   virtual void SetUpTestOnSecondaryThread() OVERRIDE {
126     {
127       ProxyAutoLock auto_lock;
128       main_thread_message_loop_proxy_->PostTask(
129           FROM_HERE,
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);
137     }
138
139     PostQuitForSecondaryThread();
140     PostQuitForMainThread();
141   }
142
143  private:
144   typedef void (*CallbackFunc)(ThreadAwareCallbackAbortTest*);
145
146   static void MainThreadCallbackBody(ThreadAwareCallbackAbortTest* thiz) {
147     // The callback should not be called.
148     ASSERT_TRUE(false);
149   }
150
151   void DeleteCallback() {
152     ProxyAutoLock auto_lock;
153     main_thread_callback_.reset(NULL);
154   }
155
156   scoped_ptr<ThreadAwareCallback<CallbackFunc> > main_thread_callback_;
157 };
158
159 }  // namespace
160
161 TEST_F(ThreadAwareCallbackTest, Basics) {
162   // ThreadAwareCallback should only be used when the proxy lock has been
163   // acquired.
164   ProxyAutoLock auto_lock;
165
166   double double_arg = 0.0;
167   bool bool_arg = false;
168   TestParameter object_arg;
169
170   // Exercise all the template code.
171   called_num = 0;
172   typedef void (*FuncType_0)();
173   scoped_ptr<ThreadAwareCallback<FuncType_0> > callback_0(
174       ThreadAwareCallback<FuncType_0>::Create(TestCallback_0));
175   callback_0->RunOnTargetThread();
176
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);
181
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);
186
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);
191
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);
196
197   typedef void (*FuncType_5)(int,
198                              const double*,
199                              bool*,
200                              TestParameter,
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,
205                                object_arg);
206
207   EXPECT_EQ(6, called_num);
208 }
209
210 TEST_F(ThreadAwareCallbackMultiThreadTest, RunOnTargetThread) {
211   RunTest();
212 }
213
214 TEST_F(ThreadAwareCallbackAbortTest, NotRunIfAborted) {
215   RunTest();
216 }
217
218 }  // namespace ppapi