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 "ppapi/tests/test_post_message.h" | 5 #include "ppapi/tests/test_post_message.h" |
6 | 6 |
7 #include <string.h> | |
7 #include <algorithm> | 8 #include <algorithm> |
8 #include <map> | 9 #include <map> |
9 #include <sstream> | 10 #include <sstream> |
10 | 11 |
11 #include "ppapi/c/dev/ppb_testing_dev.h" | 12 #include "ppapi/c/dev/ppb_testing_dev.h" |
12 #include "ppapi/c/pp_var.h" | 13 #include "ppapi/c/pp_var.h" |
14 #include "ppapi/c/ppb_file_io.h" | |
15 #include "ppapi/cpp/file_io.h" | |
16 #include "ppapi/cpp/file_ref.h" | |
17 #include "ppapi/cpp/file_system.h" | |
13 #include "ppapi/cpp/instance.h" | 18 #include "ppapi/cpp/instance.h" |
14 #include "ppapi/cpp/var.h" | 19 #include "ppapi/cpp/var.h" |
15 #include "ppapi/cpp/var_array.h" | 20 #include "ppapi/cpp/var_array.h" |
16 #include "ppapi/cpp/var_array_buffer.h" | 21 #include "ppapi/cpp/var_array_buffer.h" |
17 #include "ppapi/cpp/var_dictionary.h" | 22 #include "ppapi/cpp/var_dictionary.h" |
18 #include "ppapi/tests/pp_thread.h" | 23 #include "ppapi/tests/pp_thread.h" |
19 #include "ppapi/tests/test_utils.h" | 24 #include "ppapi/tests/test_utils.h" |
20 #include "ppapi/tests/testing_instance.h" | 25 #include "ppapi/tests/testing_instance.h" |
21 | 26 |
22 // Windows defines 'PostMessage', so we have to undef it. | 27 // Windows defines 'PostMessage', so we have to undef it. |
23 #ifdef PostMessage | 28 #ifdef PostMessage |
24 #undef PostMessage | 29 #undef PostMessage |
25 #endif | 30 #endif |
26 | 31 |
27 REGISTER_TEST_CASE(PostMessage); | 32 REGISTER_TEST_CASE(PostMessage); |
28 | 33 |
29 namespace { | 34 namespace { |
30 | 35 |
36 const char kTestFilename[] = "testfile.txt"; | |
31 const char kTestString[] = "Hello world!"; | 37 const char kTestString[] = "Hello world!"; |
32 const bool kTestBool = true; | 38 const bool kTestBool = true; |
33 const int32_t kTestInt = 42; | 39 const int32_t kTestInt = 42; |
34 const double kTestDouble = 42.0; | 40 const double kTestDouble = 42.0; |
35 | 41 |
36 // On Windows XP bots, the NonMainThread test can run very slowly. So we dial | 42 // On Windows XP bots, the NonMainThread test can run very slowly. So we dial |
37 // back the number of threads & messages when running on Windows. | 43 // back the number of threads & messages when running on Windows. |
38 #ifdef PPAPI_OS_WIN | 44 #ifdef PPAPI_OS_WIN |
39 const int32_t kThreadsToRun = 2; | 45 const int32_t kThreadsToRun = 2; |
40 const int32_t kMessagesToSendPerThread = 5; | 46 const int32_t kMessagesToSendPerThread = 5; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 js_code += "var plugin = document.getElementById('plugin');" | 160 js_code += "var plugin = document.getElementById('plugin');" |
155 "plugin.removeEventListener('message'," | 161 "plugin.removeEventListener('message'," |
156 " plugin.wait_for_messages_handler);" | 162 " plugin.wait_for_messages_handler);" |
157 "delete plugin.wait_for_messages_handler;"; | 163 "delete plugin.wait_for_messages_handler;"; |
158 instance_->EvalScript(js_code); | 164 instance_->EvalScript(js_code); |
159 } | 165 } |
160 | 166 |
161 bool TestPostMessage::Init() { | 167 bool TestPostMessage::Init() { |
162 bool success = CheckTestingInterface(); | 168 bool success = CheckTestingInterface(); |
163 | 169 |
170 core_interface_ = static_cast<const PPB_Core*>( | |
171 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); | |
172 file_system_interface_ = static_cast<const PPB_FileSystem*>( | |
173 pp::Module::Get()->GetBrowserInterface(PPB_FILESYSTEM_INTERFACE)); | |
174 var_interface_ = static_cast<const PPB_Var*>( | |
175 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE)); | |
176 var_resource_interface_ = static_cast<const PPB_VarResource_Dev*>( | |
177 pp::Module::Get()->GetBrowserInterface(PPB_VAR_RESOURCE_DEV_INTERFACE)); | |
178 if (!core_interface_ || !file_system_interface_ || !var_interface_ || | |
179 !var_resource_interface_) | |
180 return false; | |
181 | |
164 // Set up a special listener that only responds to a FINISHED_WAITING string. | 182 // Set up a special listener that only responds to a FINISHED_WAITING string. |
165 // This is for use by WaitForMessages. | 183 // This is for use by WaitForMessages. |
166 std::string js_code; | 184 std::string js_code; |
167 // Note the following code is dependent on some features of test_case.html. | 185 // Note the following code is dependent on some features of test_case.html. |
168 // E.g., it is assumed that the DOM element where the plugin is embedded has | 186 // E.g., it is assumed that the DOM element where the plugin is embedded has |
169 // an id of 'plugin', and there is a function 'IsTestingMessage' that allows | 187 // an id of 'plugin', and there is a function 'IsTestingMessage' that allows |
170 // us to ignore the messages that are intended for use by the testing | 188 // us to ignore the messages that are intended for use by the testing |
171 // framework itself. | 189 // framework itself. |
172 js_code += "var plugin = document.getElementById('plugin');" | 190 js_code += "var plugin = document.getElementById('plugin');" |
173 "var wait_for_messages_handler = function(message_event) {" | 191 "var wait_for_messages_handler = function(message_event) {" |
(...skipping 20 matching lines...) Expand all Loading... | |
194 } | 212 } |
195 | 213 |
196 void TestPostMessage::RunTests(const std::string& filter) { | 214 void TestPostMessage::RunTests(const std::string& filter) { |
197 // Note: SendInInit must be first, because it expects to receive a message | 215 // Note: SendInInit must be first, because it expects to receive a message |
198 // that was sent in Init above. | 216 // that was sent in Init above. |
199 RUN_TEST(SendInInit, filter); | 217 RUN_TEST(SendInInit, filter); |
200 RUN_TEST(SendingData, filter); | 218 RUN_TEST(SendingData, filter); |
201 RUN_TEST(SendingArrayBuffer, filter); | 219 RUN_TEST(SendingArrayBuffer, filter); |
202 RUN_TEST(SendingArray, filter); | 220 RUN_TEST(SendingArray, filter); |
203 RUN_TEST(SendingDictionary, filter); | 221 RUN_TEST(SendingDictionary, filter); |
222 RUN_TEST(SendingResource, filter); | |
204 RUN_TEST(SendingComplexVar, filter); | 223 RUN_TEST(SendingComplexVar, filter); |
205 RUN_TEST(MessageEvent, filter); | 224 RUN_TEST(MessageEvent, filter); |
206 RUN_TEST(NoHandler, filter); | 225 RUN_TEST(NoHandler, filter); |
207 RUN_TEST(ExtraParam, filter); | 226 RUN_TEST(ExtraParam, filter); |
208 if (testing_interface_->IsOutOfProcess()) | 227 if (testing_interface_->IsOutOfProcess()) |
209 RUN_TEST(NonMainThread, filter); | 228 RUN_TEST(NonMainThread, filter); |
210 } | 229 } |
211 | 230 |
212 void TestPostMessage::HandleMessage(const pp::Var& message_data) { | 231 void TestPostMessage::HandleMessage(const pp::Var& message_data) { |
213 if (message_data.is_string() && | 232 if (message_data.is_string() && |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
269 // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to | 288 // We first post a FINISHED_WAITING_MESSAGE. This should be guaranteed to |
270 // come back _after_ any other incoming messages that were already pending. | 289 // come back _after_ any other incoming messages that were already pending. |
271 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE)); | 290 instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE)); |
272 testing_interface_->RunMessageLoop(instance_->pp_instance()); | 291 testing_interface_->RunMessageLoop(instance_->pp_instance()); |
273 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know | 292 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know |
274 // that all pending messages have been slurped up. Return the number we | 293 // that all pending messages have been slurped up. Return the number we |
275 // received (which may be zero). | 294 // received (which may be zero). |
276 return message_data_.size() - message_size_before; | 295 return message_data_.size() - message_size_before; |
277 } | 296 } |
278 | 297 |
298 int TestPostMessage::PostAsyncMessageFromJavaScriptAndWait( | |
299 const std::string& func) { | |
300 // After the |func| calls callback, post both the given |message|, as well as | |
301 // the special message FINISHED_WAITING_MESSAGE. This ensures that | |
302 // RunMessageLoop correctly waits until the callback is called. | |
303 std::string js_code; | |
304 js_code += "var plugin = document.getElementById('plugin');" | |
305 "var callback = function(message) {" | |
306 " plugin.postMessage(message);" | |
307 " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');" | |
308 "};"; | |
309 js_code += "(" + func + ")(callback);"; | |
310 instance_->EvalScript(js_code); | |
311 | |
312 size_t message_size_before = message_data_.size(); | |
313 // Unlike WaitForMessages, we do not post FINISHED_WAITING_MESSAGE. This is | |
314 // because the above JavaScript code will post it for us, when the | |
315 // asynchronous operation completes. | |
316 testing_interface_->RunMessageLoop(instance_->pp_instance()); | |
317 // Now that the FINISHED_WAITING_MESSAGE has been echoed back to us, we know | |
318 // that all pending messages have been slurped up. Return the number we | |
319 // received (which may be zero). | |
320 return message_data_.size() - message_size_before; | |
321 } | |
322 | |
279 std::string TestPostMessage::CheckMessageProperties( | 323 std::string TestPostMessage::CheckMessageProperties( |
280 const pp::Var& test_data, | 324 const pp::Var& test_data, |
281 const std::vector<std::string>& properties_to_check) { | 325 const std::vector<std::string>& properties_to_check) { |
282 typedef std::vector<std::string>::const_iterator Iterator; | 326 typedef std::vector<std::string>::const_iterator Iterator; |
283 for (Iterator iter = properties_to_check.begin(); | 327 for (Iterator iter = properties_to_check.begin(); |
284 iter != properties_to_check.end(); | 328 iter != properties_to_check.end(); |
285 ++iter) { | 329 ++iter) { |
286 ASSERT_TRUE(AddEchoingListener(*iter)); | 330 ASSERT_TRUE(AddEchoingListener(*iter)); |
287 message_data_.clear(); | 331 message_data_.clear(); |
288 instance_->PostMessage(test_data); | 332 instance_->PostMessage(test_data); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
526 ASSERT_EQ(WaitForMessages(), 1); | 570 ASSERT_EQ(WaitForMessages(), 1); |
527 ASSERT_TRUE(message_data_.back().is_dictionary()); | 571 ASSERT_TRUE(message_data_.back().is_dictionary()); |
528 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back())); | 572 ASSERT_TRUE(VarsEqual(dictionary, message_data_.back())); |
529 | 573 |
530 message_data_.clear(); | 574 message_data_.clear(); |
531 ASSERT_TRUE(ClearListeners()); | 575 ASSERT_TRUE(ClearListeners()); |
532 | 576 |
533 PASS(); | 577 PASS(); |
534 } | 578 } |
535 | 579 |
580 std::string TestPostMessage::TestSendingResource() { | |
581 // Clean up after previous tests. This also swallows the message sent by Init | |
582 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | |
583 // should start with these. | |
584 WaitForMessages(); | |
585 message_data_.clear(); | |
586 ASSERT_TRUE(ClearListeners()); | |
587 | |
588 // Test sending a DOMFileSystem from JavaScript to the plugin. | |
589 // This opens a real (temporary) file using the HTML5 FileSystem API and | |
590 // writes to it. | |
591 ASSERT_TRUE(AddEchoingListener("message_event.data")); | |
592 ASSERT_EQ(message_data_.size(), 0); | |
593 std::string js_code = | |
594 "function(callback) {" | |
595 " window.webkitRequestFileSystem(window.TEMPORARY, 1024," | |
596 " function(fileSystem) {" | |
597 " fileSystem.root.getFile('"; | |
598 js_code += kTestFilename; | |
599 js_code += "', {create: true}, function(tempFile) {" | |
600 " tempFile.createWriter(function(writer) {" | |
601 " writer.onerror = function() { callback(null); };" | |
602 " writer.onwriteend = function() { callback(fileSystem); };" | |
603 " var blob = new Blob(['"; | |
604 js_code += kTestString; | |
605 js_code += "'], {'type': 'text/plain'});" | |
606 " writer.write(blob);" | |
607 " });" | |
608 " }, function() { callback(null); });" | |
609 " }, function() { callback(null); });" | |
610 "}"; | |
611 ASSERT_EQ(PostAsyncMessageFromJavaScriptAndWait(js_code), 1); | |
612 // TODO(mgiuca): Use the C++ API instead of the C API, when it is available. | |
613 PP_Var var = message_data_.back().Detach(); | |
614 PP_Resource result = var_resource_interface_->VarToResource(var); | |
615 ASSERT_TRUE(file_system_interface_->IsFileSystem(result)); | |
616 { | |
617 pp::FileSystem file_system(pp::PASS_REF, result); | |
618 std::string file_path("/"); | |
619 file_path += kTestFilename; | |
620 pp::FileRef file_ref(file_system, file_path.c_str()); | |
621 ASSERT_NE(0, file_ref.pp_resource()); | |
622 | |
623 // Read the file and test that its contents match. | |
624 pp::FileIO file_io(instance_); | |
625 ASSERT_NE(0, file_io.pp_resource()); | |
626 TestCompletionCallback callback(instance_->pp_instance(), | |
627 callback_type()); | |
628 callback.WaitForResult( | |
629 file_io.Open(file_ref, PP_FILEOPENFLAG_READ, callback.GetCallback())); | |
630 CHECK_CALLBACK_BEHAVIOR(callback); | |
631 ASSERT_EQ(PP_OK, callback.result()); | |
632 | |
633 int length = strlen(kTestString); | |
634 std::vector<char> buffer_vector(length); | |
635 char* buffer = &buffer_vector[0]; // Note: Not null-terminated! | |
dmichael (off chromium)
2013/10/30 17:47:27
I'm curious, what was wrong with the previous code
Matt Giuca
2013/10/30 23:13:54
You mean the one that read:
int length = ...;
cha
dmichael (off chromium)
2013/10/31 16:54:28
Oh, right, thanks for explaining.
FYI, you could
| |
636 callback.WaitForResult( | |
637 file_io.Read(0, buffer, length, callback.GetCallback())); | |
638 CHECK_CALLBACK_BEHAVIOR(callback); | |
639 ASSERT_EQ(length, callback.result()); | |
640 ASSERT_EQ(0, memcmp(buffer, kTestString, length)); | |
641 } | |
642 var_interface_->Release(var); | |
643 | |
644 WaitForMessages(); | |
645 message_data_.clear(); | |
646 ASSERT_TRUE(ClearListeners()); | |
647 | |
648 // TODO(mgiuca): Test roundtrip from plugin to JS and back, when the plugin to | |
649 // JS support is available. | |
650 | |
651 PASS(); | |
652 } | |
653 | |
536 std::string TestPostMessage::TestSendingComplexVar() { | 654 std::string TestPostMessage::TestSendingComplexVar() { |
537 // Clean up after previous tests. This also swallows the message sent by Init | 655 // Clean up after previous tests. This also swallows the message sent by Init |
538 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' | 656 // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit' |
539 // should start with these. | 657 // should start with these. |
540 WaitForMessages(); | 658 WaitForMessages(); |
541 message_data_.clear(); | 659 message_data_.clear(); |
542 ASSERT_TRUE(ClearListeners()); | 660 ASSERT_TRUE(ClearListeners()); |
543 | 661 |
544 pp::Var string(kTestString); | 662 pp::Var string(kTestString); |
545 pp::VarDictionary dictionary; | 663 pp::VarDictionary dictionary; |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
756 ASSERT_TRUE(received_value <= kThreadsToRun); | 874 ASSERT_TRUE(received_value <= kThreadsToRun); |
757 ++received_counts[received_value]; | 875 ++received_counts[received_value]; |
758 } | 876 } |
759 ASSERT_EQ(received_counts, expected_counts); | 877 ASSERT_EQ(received_counts, expected_counts); |
760 | 878 |
761 message_data_.clear(); | 879 message_data_.clear(); |
762 ASSERT_TRUE(ClearListeners()); | 880 ASSERT_TRUE(ClearListeners()); |
763 | 881 |
764 PASS(); | 882 PASS(); |
765 } | 883 } |
OLD | NEW |