cc: Skip commit state timer on sync compositor
[chromium-blink-merge.git] / ppapi / host / resource_message_filter_unittest.cc
blobe26d164c2f95543d2efc35954703943ee5e3d699
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 "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "base/run_loop.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread.h"
12 #include "ipc/ipc_message.h"
13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/host/host_message_context.h"
15 #include "ppapi/host/resource_host.h"
16 #include "ppapi/host/resource_message_filter.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace ppapi {
20 namespace host {
21 namespace {
23 base::WaitableEvent g_handler_completion(true, false);
25 enum TestMessageTypes {
26 MSG1_TYPE = 1,
27 MSG2_TYPE,
28 MSG3_TYPE,
29 REPLY_MSG1_TYPE,
30 REPLY_MSG2_TYPE,
31 REPLY_MSG3_TYPE,
34 // Dummy resource host which simply stores a copy of messages it handles.
35 // |SendReply| is overridden to store a copy of the outgoing message and the
36 // message loop on which it was sent.
37 class MyResourceHost : public ResourceHost {
38 public:
39 // Messages of type |msg_type| will be handled (simply by replying with a
40 // message of type |reply_msg_type|).
41 MyResourceHost(PpapiHost* host,
42 PP_Instance instance,
43 PP_Resource resource,
44 uint32 msg_type,
45 uint32 reply_msg_type)
46 : ResourceHost(host, instance, resource),
47 msg_type_(msg_type),
48 reply_msg_type_(reply_msg_type),
49 last_reply_message_loop_(NULL) {
52 const IPC::Message& last_handled_msg() const { return last_handled_msg_; }
53 const IPC::Message& last_reply_msg() const { return last_reply_msg_; }
54 base::MessageLoop* last_reply_message_loop() const {
55 return last_reply_message_loop_;
58 void AddMessageFilter(scoped_refptr<ResourceMessageFilter> filter) {
59 AddFilter(filter);
62 virtual int32_t OnResourceMessageReceived(
63 const IPC::Message& msg,
64 HostMessageContext* context) OVERRIDE {
65 last_handled_msg_ = msg;
66 if (msg.type() == msg_type_) {
67 context->reply_msg = IPC::Message(0, reply_msg_type_,
68 IPC::Message::PRIORITY_NORMAL);
69 return PP_OK;
71 return PP_ERROR_FAILED;
74 virtual void SendReply(const ReplyMessageContext& context,
75 const IPC::Message& msg) OVERRIDE {
76 last_reply_msg_ = msg;
77 last_reply_message_loop_ = base::MessageLoop::current();
78 g_handler_completion.Signal();
81 private:
82 uint32 msg_type_;
83 uint32 reply_msg_type_;
85 IPC::Message last_handled_msg_;
86 IPC::Message last_reply_msg_;
87 base::MessageLoop* last_reply_message_loop_;
90 // Dummy message filter which simply stores a copy of messages it handles.
91 // The message loop on which the message is handled is also stored for checking
92 // later.
93 class MyResourceFilter : public ResourceMessageFilter {
94 public:
95 // Messages of type |msg_type| will be handled (simply by replying with a
96 // message of type |reply_msg_type|). |io_thread| is the thread on which
97 // replies should be sent. |bg_thread| is the thread on which the message
98 // should be handled.
99 MyResourceFilter(const base::Thread& io_thread,
100 const base::Thread& bg_thread,
101 uint32 msg_type,
102 uint32 reply_msg_type)
103 : ResourceMessageFilter(io_thread.message_loop_proxy()),
104 message_loop_proxy_(bg_thread.message_loop_proxy()),
105 msg_type_(msg_type),
106 reply_msg_type_(reply_msg_type),
107 last_message_loop_(NULL) {
110 const IPC::Message& last_handled_msg() const { return last_handled_msg_; }
111 base::MessageLoop* last_message_loop() const { return last_message_loop_; }
113 virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
114 const IPC::Message& msg) OVERRIDE {
115 if (msg.type() == msg_type_)
116 return message_loop_proxy_;
117 return NULL;
120 virtual int32_t OnResourceMessageReceived(
121 const IPC::Message& msg,
122 HostMessageContext* context) OVERRIDE {
123 last_handled_msg_ = msg;
124 last_message_loop_ = base::MessageLoop::current();
125 if (msg.type() == msg_type_) {
126 context->reply_msg = IPC::Message(0, reply_msg_type_,
127 IPC::Message::PRIORITY_NORMAL);
128 return PP_OK;
130 return PP_ERROR_FAILED;
133 private:
134 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
135 uint32 msg_type_;
136 uint32 reply_msg_type_;
138 IPC::Message last_handled_msg_;
139 base::MessageLoop* last_message_loop_;
142 } // namespace
144 class ResourceMessageFilterTest : public testing::Test {
145 public:
146 void TestHandleMessageImpl() {
147 base::Thread io_thread("test_io_thread");
148 ASSERT_TRUE(io_thread.Start());
150 base::Thread bg_thread1("test_background_thread1");
151 ASSERT_TRUE(bg_thread1.Start());
152 scoped_refptr<MyResourceFilter> filter1 =
153 new MyResourceFilter(io_thread, bg_thread1, MSG1_TYPE, REPLY_MSG1_TYPE);
155 base::Thread bg_thread2("test_background_thread2");
156 ASSERT_TRUE(bg_thread2.Start());
157 scoped_refptr<MyResourceFilter> filter2 =
158 new MyResourceFilter(io_thread, bg_thread2, MSG2_TYPE, REPLY_MSG2_TYPE);
160 PP_Instance instance = 12345;
161 PP_Resource resource = 67890;
162 MyResourceHost host(NULL, instance, resource, MSG3_TYPE, REPLY_MSG3_TYPE);
163 host.AddMessageFilter(filter1);
164 host.AddMessageFilter(filter2);
166 proxy::ResourceMessageCallParams params(resource, 1);
167 params.set_has_callback();
168 HostMessageContext context(params);
169 IPC::Message message1(0, MSG1_TYPE, IPC::Message::PRIORITY_NORMAL);
170 IPC::Message message2(0, MSG2_TYPE, IPC::Message::PRIORITY_NORMAL);
171 IPC::Message message3(0, MSG3_TYPE, IPC::Message::PRIORITY_NORMAL);
173 // Message 1 handled by the first filter.
174 host.HandleMessage(message1, &context);
175 g_handler_completion.Wait();
176 EXPECT_EQ(filter1->last_handled_msg().type(), message1.type());
177 EXPECT_EQ(filter1->last_message_loop(), bg_thread1.message_loop());
178 EXPECT_EQ(host.last_reply_msg().type(),
179 static_cast<uint32>(REPLY_MSG1_TYPE));
180 EXPECT_EQ(host.last_reply_message_loop(), io_thread.message_loop());
181 g_handler_completion.Reset();
183 // Message 2 handled by the second filter.
184 host.HandleMessage(message2, &context);
185 g_handler_completion.Wait();
186 EXPECT_EQ(filter2->last_handled_msg().type(), message2.type());
187 EXPECT_EQ(filter2->last_message_loop(), bg_thread2.message_loop());
188 EXPECT_EQ(host.last_reply_msg().type(),
189 static_cast<uint32>(REPLY_MSG2_TYPE));
190 EXPECT_EQ(host.last_reply_message_loop(), io_thread.message_loop());
191 g_handler_completion.Reset();
193 // Message 3 handled by the resource host.
194 host.HandleMessage(message3, &context);
195 EXPECT_EQ(host.last_handled_msg().type(), message3.type());
196 EXPECT_EQ(host.last_reply_msg().type(),
197 static_cast<uint32>(REPLY_MSG3_TYPE));
199 io_thread.Stop();
200 bg_thread1.Stop();
201 bg_thread2.Stop();
205 // Test that messages are filtered correctly and handlers are run on the correct
206 // threads.
207 TEST_F(ResourceMessageFilterTest, TestHandleMessage) {
208 // ResourceMessageFilter instances need to be created on a thread with message
209 // loop. Therefore, we create a message loop and run the testing logic as a
210 // task on it.
211 base::MessageLoop main_message_loop;
213 // It should be safe to use base::Unretained() because the object won't be
214 // destroyed before the task is run.
215 main_message_loop.PostTask(
216 FROM_HERE,
217 base::Bind(&ResourceMessageFilterTest::TestHandleMessageImpl,
218 base::Unretained(this)));
220 base::RunLoop().RunUntilIdle();
223 } // namespace proxy
224 } // namespace ppapi