OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 #include "base/bind.h" |
| 6 #include "base/bind_helpers.h" |
5 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
6 #include "base/message_loop/message_loop_proxy.h" | 8 #include "base/message_loop/message_loop_proxy.h" |
| 9 #include "base/run_loop.h" |
7 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
8 #include "base/threading/thread.h" | 11 #include "base/threading/thread.h" |
9 #include "ipc/ipc_message.h" | 12 #include "ipc/ipc_message.h" |
10 #include "ppapi/c/pp_errors.h" | 13 #include "ppapi/c/pp_errors.h" |
11 #include "ppapi/host/host_message_context.h" | 14 #include "ppapi/host/host_message_context.h" |
12 #include "ppapi/host/resource_host.h" | 15 #include "ppapi/host/resource_host.h" |
13 #include "ppapi/host/resource_message_filter.h" | 16 #include "ppapi/host/resource_message_filter.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
15 | 18 |
16 namespace ppapi { | 19 namespace ppapi { |
17 namespace host { | 20 namespace host { |
18 | |
19 typedef testing::Test ResourceMessageFilterTest; | |
20 | |
21 namespace { | 21 namespace { |
22 | 22 |
23 base::WaitableEvent g_handler_completion(true, false); | 23 base::WaitableEvent g_handler_completion(true, false); |
24 | 24 |
25 enum TestMessageTypes { | 25 enum TestMessageTypes { |
26 MSG1_TYPE = 1, | 26 MSG1_TYPE = 1, |
27 MSG2_TYPE, | 27 MSG2_TYPE, |
28 MSG3_TYPE, | 28 MSG3_TYPE, |
29 REPLY_MSG1_TYPE, | 29 REPLY_MSG1_TYPE, |
30 REPLY_MSG2_TYPE, | 30 REPLY_MSG2_TYPE, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; | 134 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; |
135 uint32 msg_type_; | 135 uint32 msg_type_; |
136 uint32 reply_msg_type_; | 136 uint32 reply_msg_type_; |
137 | 137 |
138 IPC::Message last_handled_msg_; | 138 IPC::Message last_handled_msg_; |
139 base::MessageLoop* last_message_loop_; | 139 base::MessageLoop* last_message_loop_; |
140 }; | 140 }; |
141 | 141 |
142 } // namespace | 142 } // namespace |
143 | 143 |
| 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()); |
| 149 |
| 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); |
| 154 |
| 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); |
| 159 |
| 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); |
| 165 |
| 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); |
| 172 |
| 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(); |
| 182 |
| 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(); |
| 192 |
| 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)); |
| 198 |
| 199 io_thread.Stop(); |
| 200 bg_thread1.Stop(); |
| 201 bg_thread2.Stop(); |
| 202 } |
| 203 }; |
| 204 |
144 // Test that messages are filtered correctly and handlers are run on the correct | 205 // Test that messages are filtered correctly and handlers are run on the correct |
145 // threads. | 206 // threads. |
146 TEST_F(ResourceMessageFilterTest, TestHandleMessage) { | 207 TEST_F(ResourceMessageFilterTest, TestHandleMessage) { |
147 base::Thread io_thread("test_io_thread"); | 208 // ResourceMessageFilter instances need to be created on a thread with message |
148 ASSERT_TRUE(io_thread.Start()); | 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; |
149 | 212 |
150 base::Thread bg_thread1("test_background_thread1"); | 213 // It should be safe to use base::Unretained() because the object won't be |
151 ASSERT_TRUE(bg_thread1.Start()); | 214 // destroyed before the task is run. |
152 scoped_refptr<MyResourceFilter> filter1 = | 215 main_message_loop.PostTask( |
153 new MyResourceFilter(io_thread, bg_thread1, MSG1_TYPE, REPLY_MSG1_TYPE); | 216 FROM_HERE, |
| 217 base::Bind(&ResourceMessageFilterTest::TestHandleMessageImpl, |
| 218 base::Unretained(this))); |
154 | 219 |
155 base::Thread bg_thread2("test_background_thread2"); | 220 base::RunLoop().RunUntilIdle(); |
156 ASSERT_TRUE(bg_thread2.Start()); | |
157 scoped_refptr<MyResourceFilter> filter2 = | |
158 new MyResourceFilter(io_thread, bg_thread2, MSG2_TYPE, REPLY_MSG2_TYPE); | |
159 | |
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); | |
165 | |
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); | |
172 | |
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(), static_cast<uint32>(REPLY_MSG1_TYPE)); | |
179 EXPECT_EQ(host.last_reply_message_loop(), io_thread.message_loop()); | |
180 g_handler_completion.Reset(); | |
181 | |
182 // Message 2 handled by the second filter. | |
183 host.HandleMessage(message2, &context); | |
184 g_handler_completion.Wait(); | |
185 EXPECT_EQ(filter2->last_handled_msg().type(), message2.type()); | |
186 EXPECT_EQ(filter2->last_message_loop(), bg_thread2.message_loop()); | |
187 EXPECT_EQ(host.last_reply_msg().type(), static_cast<uint32>(REPLY_MSG2_TYPE)); | |
188 EXPECT_EQ(host.last_reply_message_loop(), io_thread.message_loop()); | |
189 g_handler_completion.Reset(); | |
190 | |
191 // Message 3 handled by the resource host. | |
192 host.HandleMessage(message3, &context); | |
193 EXPECT_EQ(host.last_handled_msg().type(), message3.type()); | |
194 EXPECT_EQ(host.last_reply_msg().type(), static_cast<uint32>(REPLY_MSG3_TYPE)); | |
195 | |
196 io_thread.Stop(); | |
197 bg_thread1.Stop(); | |
198 bg_thread2.Stop(); | |
199 } | 221 } |
200 | 222 |
201 } // namespace proxy | 223 } // namespace proxy |
202 } // namespace ppapi | 224 } // namespace ppapi |
OLD | NEW |