Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(877)

Side by Side Diff: ppapi/tests/test_message_handler.cc

Issue 674203005: PPAPI: Make TestMessageHandler.Exceptions work (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: review comments Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ppapi/tests/test_message_handler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "ppapi/tests/test_message_handler.h" 5 #include "ppapi/tests/test_message_handler.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <map> 9 #include <map>
10 #include <sstream> 10 #include <sstream>
(...skipping 24 matching lines...) Expand all
35 #undef PostMessage 35 #undef PostMessage
36 #endif 36 #endif
37 37
38 REGISTER_TEST_CASE(MessageHandler); 38 REGISTER_TEST_CASE(MessageHandler);
39 39
40 namespace { 40 namespace {
41 41
42 // Created and destroyed on the main thread. All public methods should be called 42 // Created and destroyed on the main thread. All public methods should be called
43 // on the main thread. Most data members are only accessed on the main thread. 43 // on the main thread. Most data members are only accessed on the main thread.
44 // (Though it handles messages on the background thread). 44 // (Though it handles messages on the background thread).
45 class EchoingMessageHandler : public pp::MessageHandler { 45 class MyMessageHandler : public pp::MessageHandler {
46 public: 46 public:
47 explicit EchoingMessageHandler(TestingInstance* instance, 47 explicit MyMessageHandler(TestingInstance* instance,
48 const pp::MessageLoop& loop) 48 const pp::MessageLoop& loop)
49 : testing_instance_(instance), 49 : testing_instance_(instance),
50 message_handler_loop_(loop), 50 message_handler_loop_(loop),
51 is_registered_(false), 51 is_registered_(false),
52 test_finished_event_(instance->pp_instance()), 52 test_finished_event_(instance->pp_instance()),
53 destroy_event_(instance->pp_instance()) { 53 destroy_event_(instance->pp_instance()),
54 async_message_received_(instance->pp_instance()) {
54 AssertOnMainThread(); 55 AssertOnMainThread();
55 } 56 }
56 void Register() { 57 void Register() {
57 AssertOnMainThread(); 58 AssertOnMainThread();
58 assert(!is_registered_); 59 assert(!is_registered_);
59 int32_t result = 60 int32_t result =
60 testing_instance_->RegisterMessageHandler(this, message_handler_loop_); 61 testing_instance_->RegisterMessageHandler(this, message_handler_loop_);
61 if (result == PP_OK) { 62 if (result == PP_OK) {
62 is_registered_ = true; 63 is_registered_ = true;
63 } else { 64 } else {
(...skipping 24 matching lines...) Expand all
88 assert(!is_registered_); 89 assert(!is_registered_);
89 destroy_event_.Wait(); 90 destroy_event_.Wait();
90 destroy_event_.Reset(); 91 destroy_event_.Reset();
91 // Now that we know Destroy() has been called, we know errors_ isn't being 92 // Now that we know Destroy() has been called, we know errors_ isn't being
92 // written on the MessageHandler thread anymore. So we can safely read it 93 // written on the MessageHandler thread anymore. So we can safely read it
93 // here on the main thread (since destroy_event_ gave us a memory barrier). 94 // here on the main thread (since destroy_event_ gave us a memory barrier).
94 std::string temp_errors; 95 std::string temp_errors;
95 errors_.swap(temp_errors); 96 errors_.swap(temp_errors);
96 return temp_errors; 97 return temp_errors;
97 } 98 }
99 pp::Var WaitForAsyncMessage() {
100 async_message_received_.Wait();
101 pp::Var var_to_return = last_async_message_received_;
102 last_async_message_received_ = pp::Var();
103 async_message_received_.Reset();
104 return var_to_return;
105 }
98 private: 106 private:
99 static void AssertOnMainThread() { 107 static void AssertOnMainThread() {
100 assert(pp::MessageLoop::GetForMainThread() == 108 assert(pp::MessageLoop::GetForMainThread() ==
101 pp::MessageLoop::GetCurrent()); 109 pp::MessageLoop::GetCurrent());
102 } 110 }
103 void AddError(const std::string& error) { 111 void AddError(const std::string& error) {
104 if (!error.empty()) { 112 if (!error.empty()) {
105 if (!errors_.empty()) 113 if (!errors_.empty())
106 errors_ += "<p>"; 114 errors_ += "<p>";
107 errors_ += error; 115 errors_ += error;
108 } 116 }
109 } 117 }
110 virtual void HandleMessage(pp::InstanceHandle instance, const pp::Var& var) { 118 virtual void HandleMessage(pp::InstanceHandle instance, const pp::Var& var) {
111 if (pp::MessageLoop::GetCurrent() != message_handler_loop_) 119 if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
112 AddError("HandleMessage was called on the wrong thread!"); 120 AddError("HandleMessage was called on the wrong thread!");
113 if (instance.pp_instance() != testing_instance_->pp_instance()) 121 if (instance.pp_instance() != testing_instance_->pp_instance())
114 AddError("HandleMessage was passed the wrong instance!"); 122 AddError("HandleMessage was passed the wrong instance!");
115 if (var.is_string() && var.AsString() == "FINISHED_TEST") 123 if (var.is_string() && var.AsString() == "FINISHED_TEST") {
116 test_finished_event_.Signal(); 124 test_finished_event_.Signal();
117 else 125 } else {
118 testing_instance_->PostMessage(var); 126 // Any client causing a message to arrive must wait for the message
127 // before continuing. See WaitForAsyncMessage().
128 assert(last_async_message_received_.is_undefined());
129 last_async_message_received_ = var;
130 async_message_received_.Signal();
131 }
119 } 132 }
120 133
121 virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance, 134 virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance,
122 const pp::Var& var) { 135 const pp::Var& var) {
123 if (pp::MessageLoop::GetCurrent() != message_handler_loop_) 136 if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
124 AddError("HandleBlockingMessage was called on the wrong thread!"); 137 AddError("HandleBlockingMessage was called on the wrong thread!");
125 if (instance.pp_instance() != testing_instance_->pp_instance()) 138 if (instance.pp_instance() != testing_instance_->pp_instance())
126 AddError("HandleBlockingMessage was passed the wrong instance!"); 139 AddError("HandleBlockingMessage was passed the wrong instance!");
127 140
128 // Attempt a blocking operation; make sure it's disallowed. 141 // Attempt a blocking operation; make sure it's disallowed.
(...skipping 29 matching lines...) Expand all
158 // is_registered_ is only read/written on the main thread. 171 // is_registered_ is only read/written on the main thread.
159 bool is_registered_; 172 bool is_registered_;
160 173
161 // errors_ is written on the MessageHandler thread. When Destroy() is 174 // errors_ is written on the MessageHandler thread. When Destroy() is
162 // called, we stop writing to errors_ and signal destroy_event_. This causes 175 // called, we stop writing to errors_ and signal destroy_event_. This causes
163 // a memory barrier, so it's safe to read errors_ after that. 176 // a memory barrier, so it's safe to read errors_ after that.
164 std::string errors_; 177 std::string errors_;
165 NestedEvent test_finished_event_; 178 NestedEvent test_finished_event_;
166 NestedEvent destroy_event_; 179 NestedEvent destroy_event_;
167 180
181 pp::Var last_async_message_received_;
182 NestedEvent async_message_received_;
183
168 // Undefined & private to disallow copy and assign. 184 // Undefined & private to disallow copy and assign.
169 EchoingMessageHandler(const EchoingMessageHandler&); 185 MyMessageHandler(const MyMessageHandler&);
170 EchoingMessageHandler& operator=(const EchoingMessageHandler&); 186 MyMessageHandler& operator=(const MyMessageHandler&);
171 }; 187 };
172 188
173 void FakeHandleMessage(PP_Instance instance, 189 void FakeHandleMessage(PP_Instance instance,
174 void* user_data, 190 void* user_data,
175 const PP_Var* message_data) {} 191 const PP_Var* message_data) {}
176 void FakeHandleBlockingMessage(PP_Instance instance, 192 void FakeHandleBlockingMessage(PP_Instance instance,
177 void* user_data, 193 void* user_data,
178 const PP_Var* message_data, 194 const PP_Var* message_data,
179 PP_Var* result) {} 195 PP_Var* result) {}
180 void FakeDestroy(PP_Instance instance, void* user_data) {} 196 void FakeDestroy(PP_Instance instance, void* user_data) {}
181 197
182 } // namespace 198 } // namespace
183 199
184 TestMessageHandler::TestMessageHandler(TestingInstance* instance) 200 TestMessageHandler::TestMessageHandler(TestingInstance* instance)
185 : TestCase(instance), 201 : TestCase(instance),
202 message_received_(instance->pp_instance()),
186 ppb_messaging_if_(NULL), 203 ppb_messaging_if_(NULL),
187 handler_thread_(instance), 204 handler_thread_(instance) {
188 message_received_(instance->pp_instance()) {
189 } 205 }
190 206
191 TestMessageHandler::~TestMessageHandler() { 207 TestMessageHandler::~TestMessageHandler() {
192 handler_thread_.Join(); 208 handler_thread_.Join();
193 } 209 }
194 210
195 bool TestMessageHandler::Init() { 211 bool TestMessageHandler::Init() {
196 ppb_messaging_if_ = static_cast<const PPB_Messaging_1_2*>( 212 ppb_messaging_if_ = static_cast<const PPB_Messaging_1_2*>(
197 pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_2)); 213 pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_2));
198 return ppb_messaging_if_ && 214 return ppb_messaging_if_ &&
199 CheckTestingInterface() && 215 CheckTestingInterface() &&
200 handler_thread_.Start(); 216 handler_thread_.Start();
201 } 217 }
202 218
203 void TestMessageHandler::RunTests(const std::string& filter) { 219 void TestMessageHandler::RunTests(const std::string& filter) {
204 RUN_TEST(RegisterErrorConditions, filter); 220 RUN_TEST(RegisterErrorConditions, filter);
205 RUN_TEST(PostMessageAndAwaitResponse, filter); 221 RUN_TEST(PostMessageAndAwaitResponse, filter);
206 RUN_TEST(Exceptions, filter); 222 RUN_TEST(Exceptions, filter);
207 } 223 }
208 224
209 void TestMessageHandler::HandleMessage(const pp::Var& message_data) { 225 void TestMessageHandler::HandleMessage(const pp::Var& message_data) {
210 if (instance()->current_test_name() == "Exceptions") { 226 if (instance()->current_test_name() == "Exceptions") {
211 // For TestPostMessageAndAwaitResponse(), all messages should go to the 227 // For TestPostMessageAndAwaitResponse(), all messages should go to the
212 // background thread message handler. 228 // background thread message handler.
213 assert(false); 229 assert(false);
214 } else { 230 } else {
215 if (message_data.is_string()) { 231 // Any subtest causing a message to arrive here must wait for it before
216 last_message_ = message_data.AsString(); 232 // continuing. See WaitForMessage().
217 } else { 233 assert(last_message_.is_undefined());
218 last_message_ = "message_data was not a string!"; 234 last_message_ = message_data;
219 }
220 message_received_.Signal(); 235 message_received_.Signal();
221 } 236 }
222 } 237 }
223 238
224 std::string TestMessageHandler::TestRegisterErrorConditions() { 239 std::string TestMessageHandler::TestRegisterErrorConditions() {
225 { 240 {
226 // Test registering with the main thread as the message loop. 241 // Test registering with the main thread as the message loop.
227 PPP_MessageHandler_0_2 fake_ppp_message_handler = { 242 PPP_MessageHandler_0_2 fake_ppp_message_handler = {
228 &FakeHandleMessage, &FakeHandleBlockingMessage, &FakeDestroy 243 &FakeHandleMessage, &FakeHandleBlockingMessage, &FakeDestroy
229 }; 244 };
(...skipping 17 matching lines...) Expand all
247 reinterpret_cast<void*>(0xdeadbeef), 262 reinterpret_cast<void*>(0xdeadbeef),
248 &bad_ppp_ifs[i], 263 &bad_ppp_ifs[i],
249 handler_thread_.message_loop().pp_resource()); 264 handler_thread_.message_loop().pp_resource());
250 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); 265 ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
251 } 266 }
252 } 267 }
253 PASS(); 268 PASS();
254 } 269 }
255 270
256 std::string TestMessageHandler::TestPostMessageAndAwaitResponse() { 271 std::string TestMessageHandler::TestPostMessageAndAwaitResponse() {
257 EchoingMessageHandler handler(instance(), 272 MyMessageHandler handler(instance(),
258 handler_thread_.message_loop()); 273 handler_thread_.message_loop());
259 // Test doing a sync call before the handler is registered.
260 handler.Register(); 274 handler.Register();
261 std::string js_code("var plugin = document.getElementById('plugin');\n"); 275 std::string js_code("var plugin = document.getElementById('plugin');\n");
262 js_code += "var result = undefined;\n"; 276 js_code += "var result = undefined;\n";
263 const char* const values_to_test[] = { 277 const char* const values_to_test[] = {
264 "5", 278 "5",
265 "undefined", 279 "undefined",
266 "1.5", 280 "1.5",
267 "'hello'", 281 "'hello'",
268 "{'key': 'value', 'array_key': [1, 2, 3, 4, 5]}", 282 "{'key': 'value', 'array_key': [1, 2, 3, 4, 5]}",
269 NULL 283 NULL
(...skipping 12 matching lines...) Expand all
282 instance_->EvalScript(js_code); 296 instance_->EvalScript(js_code);
283 instance_->EvalScript("plugin.postMessage('FINISHED_TEST');\n"); 297 instance_->EvalScript("plugin.postMessage('FINISHED_TEST');\n");
284 handler.WaitForTestFinishedMessage(); 298 handler.WaitForTestFinishedMessage();
285 handler.Unregister(); 299 handler.Unregister();
286 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); 300 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy());
287 301
288 PASS(); 302 PASS();
289 } 303 }
290 304
291 std::string TestMessageHandler::TestExceptions() { 305 std::string TestMessageHandler::TestExceptions() {
292 EchoingMessageHandler handler(instance(), 306 MyMessageHandler handler(instance(),
293 handler_thread_.message_loop()); 307 handler_thread_.message_loop());
294 { 308 {
295 // First, try sending a blocking message when there is no handler 309 // First, try sending a blocking message when there is no handler
296 // registered. It should throw an exception. 310 // registered. It should throw an exception.
297 std::string js_code( 311 std::string js_code(
298 "var plugin = document.getElementById('plugin');\n" 312 "var plugin = document.getElementById('plugin');\n"
299 "var caught_exception = false;\n" 313 "var caught_exception = false;\n"
300 "try {\n" 314 "try {\n"
301 " plugin.postMessageAndAwaitResponse('Hello!');\n" 315 " plugin.postMessageAndAwaitResponse('Hello!');\n"
302 "} catch (err) {\n" 316 "} catch (err) {\n"
303 " caught_exception = true;\n" 317 " caught_exception = true;\n"
304 "}\n" 318 "}\n"
305 "plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n"); 319 "plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n");
306 instance_->EvalScript(js_code); 320 instance_->EvalScript(js_code);
307 message_received_.Wait(); 321 // Note that we want to wait for the Instance to get the SUCCESS/FAIL
308 ASSERT_EQ("SUCCESS", last_message_); 322 // message here. |message_handler| is not yet registered, so the message
323 // goes to the instance instead.
324 pp::Var msg = WaitForMessage();
325 ASSERT_TRUE(msg.is_string());
326 ASSERT_EQ("SUCCESS", msg.AsString());
309 } 327 }
310 handler.Register(); 328 handler.Register();
311 { 329 {
312 // Now that a handler is registered, try requesting and sending a 330 // Now that a handler is registered, try requesting and sending a
313 // FileSystem. It should throw an exception. The file system is opened 331 // FileSystem. It should throw an exception. The file system is opened
314 // asynchronously. What *should* happen is that it opens successfully, then 332 // asynchronously. What *should* happen is that it opens successfully, then
315 // we try to send it via postMessageAndAwaitResponse, which fails with an 333 // we try to send it via postMessageAndAwaitResponse, which fails with an
316 // exception. The test could fail either because the filesystem doesn't 334 // exception. The test could fail either because the filesystem doesn't
317 // open or because postMessageAndAwaitResponse doesn't throw an exception. 335 // open or because postMessageAndAwaitResponse doesn't throw an exception.
318 std::string js_code( 336 std::string js_code(
319 "var plugin = document.getElementById('plugin');\n" 337 "var plugin = document.getElementById('plugin');\n"
320 "function gotFileSystem(fs) {\n" 338 "function gotFileSystem(fs) {\n"
321 " var caught_exception = false;\n" 339 " var caught_exception = false;\n"
322 " try {\n" 340 " try {\n"
323 " plugin.postMessageAndAwaitResponse(fs);\n" 341 " plugin.postMessageAndAwaitResponse(fs);\n"
324 " } catch (err) {\n" 342 " } catch (err) {\n"
325 " caught_exception = true;\n" 343 " caught_exception = true;\n"
326 " }\n" 344 " }\n"
327 " plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n" 345 " plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n"
328 "}\n" 346 "}\n"
329 "function fileSystemError() {\n" 347 "function fileSystemError() {\n"
330 " plugin.postMessage('Failed to open filesystem');\n" 348 " plugin.postMessage('Failed to open filesystem');\n"
331 "}\n" 349 "}\n"
332 "window.webkitRequestFileSystem(\n" 350 "window.webkitRequestFileSystem(\n"
333 " window.Temporary, 1024, gotFileSystem, fileSystemError)\n"); 351 " window.Temporary, 1024, gotFileSystem, fileSystemError)\n");
334 instance_->EvalScript(js_code); 352 instance_->EvalScript(js_code);
335 message_received_.Wait(); 353 pp::Var msg = handler.WaitForAsyncMessage();
336 ASSERT_EQ("SUCCESS", last_message_); 354 ASSERT_EQ(PP_VARTYPE_STRING, msg.pp_var().type);
355 ASSERT_EQ("SUCCESS", msg.AsString());
337 } 356 }
338 handler.Unregister(); 357 handler.Unregister();
339 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy()); 358 ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy());
340 359
341 PASS(); 360 PASS();
342 } 361 }
343 362
363 pp::Var TestMessageHandler::WaitForMessage() {
364 message_received_.Wait();
365 pp::Var var_to_return = last_message_;
366 last_message_ = pp::Var();
367 message_received_.Reset();
368 return var_to_return;
369 }
370
OLDNEW
« no previous file with comments | « ppapi/tests/test_message_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698