diff options
author | teravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-26 21:25:11 +0000 |
---|---|---|
committer | teravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-26 21:25:11 +0000 |
commit | 7d3b2545b5b449f1454e40a0865c8126bf4f119b (patch) | |
tree | b35ffdd576e090ee37597bfe797d704e90761a89 /ppapi | |
parent | 6df1c805eaa6cbab95da9003357fafb416cba326 (diff) | |
download | chromium_src-7d3b2545b5b449f1454e40a0865c8126bf4f119b.zip chromium_src-7d3b2545b5b449f1454e40a0865c8126bf4f119b.tar.gz chromium_src-7d3b2545b5b449f1454e40a0865c8126bf4f119b.tar.bz2 |
Pepper: Extension for SocketPpapiTest to ppapi/.
As part of building a test framework for Pepper interactions with extensions,
we should move the extension sources under ppapi/tests.
This creates a ppapi/tests/extensions directory which will contain all of the
plugin side extensions.
SocketPpapiTest will be moved outside socket_apitest.cc in another change.
R=asargent@chromium.org, dmichael@chromium.org, yzshen@chromium.org, yzshen1
TBR=maruel
BUG=
Review URL: https://codereview.chromium.org/23540007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225570 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/tests/extensions/extensions.gyp | 33 | ||||
-rw-r--r-- | ppapi/tests/extensions/socket/controller.js | 34 | ||||
-rw-r--r-- | ppapi/tests/extensions/socket/index.html | 11 | ||||
-rw-r--r-- | ppapi/tests/extensions/socket/main.js | 7 | ||||
-rw-r--r-- | ppapi/tests/extensions/socket/manifest.json | 22 | ||||
-rw-r--r-- | ppapi/tests/extensions/socket/test_socket.cc | 654 |
6 files changed, 761 insertions, 0 deletions
diff --git a/ppapi/tests/extensions/extensions.gyp b/ppapi/tests/extensions/extensions.gyp new file mode 100644 index 0000000..d063b83f4 --- /dev/null +++ b/ppapi/tests/extensions/extensions.gyp @@ -0,0 +1,33 @@ +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'includes': [ + '../../../ppapi/ppapi_nacl_test_common.gypi', + ], + 'targets': [ + { + 'target_name': 'ppapi_tests_extensions_socket', + 'type': 'none', + 'variables': { + 'nexe_target': 'ppapi_tests_extensions_socket', + 'build_newlib': 1, + 'build_glibc': 0, + 'build_pnacl_newlib': 0, + 'nexe_destination_dir': 'test_data/ppapi/tests/extensions/socket', + 'sources': [ + 'socket/test_socket.cc', + '<(DEPTH)/ppapi/tests/test_utils.cc', + '<(DEPTH)/ppapi/tests/test_utils.h', + ], + 'test_files': [ + 'socket/controller.js', + 'socket/index.html', + 'socket/main.js', + 'socket/manifest.json', + ], + }, + }, + ], +} diff --git a/ppapi/tests/extensions/socket/controller.js b/ppapi/tests/extensions/socket/controller.js new file mode 100644 index 0000000..b6aa402 --- /dev/null +++ b/ppapi/tests/extensions/socket/controller.js @@ -0,0 +1,34 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var control_message; + +function testAll() { + var nacl_module = document.getElementById('nacl_module'); + // The plugin will start the corresponding test and post a message back when + // the test is done. If the test has failed, the message is a description of + // the error; otherwise the message is empty. + nacl_module.postMessage(control_message); +} + +var onControlMessageReceived = function(message) { + control_message = message; + chrome.test.runTests([testAll]); +} + +var onPluginMessageReceived = function(message) { + if (message.data == "ready") { + chrome.test.sendMessage("info_please", onControlMessageReceived); + } else if (message.data) { + chrome.test.fail(message.data); + } else { + chrome.test.succeed(); + } +}; + +window.onload = function() { + var nacl_module = document.getElementById('nacl_module'); + nacl_module.addEventListener("message", onPluginMessageReceived, false); +}; + diff --git a/ppapi/tests/extensions/socket/index.html b/ppapi/tests/extensions/socket/index.html new file mode 100644 index 0000000..028abd6 --- /dev/null +++ b/ppapi/tests/extensions/socket/index.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> + <title>chrome.socket</title> + <script src="controller.js"></script> +</head> +<body> + <embed id="nacl_module" src="ppapi_tests_extensions_socket.nmf" + type="application/x-nacl" /> +</body> +</html> diff --git a/ppapi/tests/extensions/socket/main.js b/ppapi/tests/extensions/socket/main.js new file mode 100644 index 0000000..68957dc --- /dev/null +++ b/ppapi/tests/extensions/socket/main.js @@ -0,0 +1,7 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('index.html', {width: 500, height: 500}); +}); diff --git a/ppapi/tests/extensions/socket/manifest.json b/ppapi/tests/extensions/socket/manifest.json new file mode 100644 index 0000000..635f97a --- /dev/null +++ b/ppapi/tests/extensions/socket/manifest.json @@ -0,0 +1,22 @@ +{ + "manifest_version": 2, + "name": "chrome.socket", + "version": "0.1", + "description": "end-to-end browser test for chrome.socket API in Pepper", + "app": { + "background": { + "scripts": ["main.js"] + } + }, + "permissions": [ + { + "socket": [ + "tcp-connect", + "tcp-listen", + "udp-send-to", + "udp-bind", + "udp-multicast-membership" + ] + } + ] +} diff --git a/ppapi/tests/extensions/socket/test_socket.cc b/ppapi/tests/extensions/socket/test_socket.cc new file mode 100644 index 0000000..487c53f --- /dev/null +++ b/ppapi/tests/extensions/socket/test_socket.cc @@ -0,0 +1,654 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <cstdarg> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +#include "ppapi/c/ppb_console.h" +#include "ppapi/cpp/extensions/dev/socket_dev.h" +#include "ppapi/cpp/instance.h" +#include "ppapi/cpp/module.h" +#include "ppapi/cpp/var.h" +#include "ppapi/cpp/var_array_buffer.h" +#include "ppapi/tests/test_utils.h" + +using namespace pp; +using namespace pp::ext; + +namespace { + +const char* const kSendContents = "0100000005320000005hello"; +const char* const kReceiveContentsPrefix = "0100000005320000005"; +const size_t kReceiveContentsSuffixSize = 11; + +const char* const kMulticastAddress = "237.132.100.133"; +const int32_t kMulticastPort = 11103; +const char* const kMulticastMessage = "hello world!"; + +} // namespace + +class MyInstance : public Instance { + public: + explicit MyInstance(PP_Instance instance) + : Instance(instance), + socket_(InstanceHandle(instance)), + console_interface_(NULL), + port_(0) { + } + virtual ~MyInstance() { + } + + virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { + console_interface_ = static_cast<const PPB_Console*>( + Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE)); + + if (!console_interface_) + return false; + + PostMessage(Var("ready")); + return true; + } + + virtual void HandleMessage(const pp::Var& message_data) { + std::string output; + do { + if (!message_data.is_string()) { + output = "Invalid control message."; + break; + } + + std::string control_message = message_data.AsString(); + std::vector<std::string> parts; + size_t pos = 0; + size_t next_match = 0; + while (pos < control_message.size()) { + next_match = control_message.find(':', pos); + if (next_match == std::string::npos) + next_match = control_message.size(); + parts.push_back(control_message.substr(pos, next_match - pos)); + pos = next_match + 1; + } + + if (parts.size() != 3) { + output = "Invalid protocol/address/port input."; + break; + } + + test_type_ = parts[0]; + address_ = parts[1]; + port_ = atoi(parts[2].c_str()); + Log(PP_LOGLEVEL_LOG, "Running tests, protocol %s, server %s:%d", + test_type_.c_str(), address_.c_str(), port_); + + if (test_type_ == "tcp_server") { + output = TestServerSocket(); + } else if (test_type_ == "multicast") { + output = TestMulticast(); + } else { + output = TestClientSocket(); + } + } while (false); + + NotifyTestDone(output); + } + + private: + std::string TestServerSocket() { + int32_t socket_id = 0; + { + TestExtCompletionCallbackWithOutput<socket::CreateInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.Create( + socket::SocketType_Dev(socket::SocketType_Dev::TCP), + Optional<socket::CreateOptions_Dev>(), callback.GetCallback())); + if (callback.result() != PP_OK) + return "Create(): failed."; + socket_id = callback.output().socket_id(); + if (socket_id <= 0) + return "Create(): invalid socket ID."; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.Listen( + socket_id, address_, port_, Optional<int32_t>(), + callback.GetCallback())); + if (callback.result() != PP_OK) + return "Listen(): failed."; + if (callback.output() != 0) + return "Listen(): failed."; + } + + int32_t client_socket_id = 0; + { + TestExtCompletionCallbackWithOutput<socket::CreateInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.Create( + socket::SocketType_Dev(socket::SocketType_Dev::TCP), + Optional<socket::CreateOptions_Dev>(), callback.GetCallback())); + if (callback.result() != PP_OK) + return "Create(): failed."; + client_socket_id = callback.output().socket_id(); + if (client_socket_id <= 0) + return "Create(): invalid socket ID."; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.Connect( + client_socket_id, address_, port_, callback.GetCallback())); + if (callback.result() != PP_OK) + return "Connect(): failed."; + if (callback.output() != 0) + return "Connect(): failed."; + } + + int32_t accepted_socket_id = 0; + { + TestExtCompletionCallbackWithOutput<socket::AcceptInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.Accept(socket_id, callback.GetCallback())); + if (callback.result() != PP_OK) + return "Accept(): failed."; + socket::AcceptInfo_Dev accept_info = callback.output(); + if (accept_info.result_code() != 0 || !accept_info.socket_id().IsSet()) + return "Accept(): failed."; + accepted_socket_id = *accept_info.socket_id(); + } + + size_t bytes_written = 0; + { + TestExtCompletionCallbackWithOutput<socket::WriteInfo_Dev> + callback(pp_instance()); + VarArrayBuffer array_buffer = ConvertToArrayBuffer(kSendContents); + callback.WaitForResult(socket_.Write(client_socket_id, array_buffer, + callback.GetCallback())); + if (callback.result() != PP_OK) + return "Write(): failed."; + socket::WriteInfo_Dev write_info = callback.output(); + bytes_written = static_cast<size_t>(write_info.bytes_written()); + if (bytes_written <= 0) + return "Write(): did not write any bytes."; + } + + { + TestExtCompletionCallbackWithOutput<socket::ReadInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.Read( + accepted_socket_id, Optional<int32_t>(), callback.GetCallback())); + if (callback.result() != PP_OK) + return "Read(): failed."; + + std::string data_string = ConvertFromArrayBuffer( + &callback.output().data()); + if (data_string.compare(0, std::string::npos, kSendContents, + bytes_written) != 0) { + return "Read(): Received data does not match."; + } + } + + socket_.Destroy(client_socket_id); + socket_.Destroy(accepted_socket_id); + socket_.Destroy(socket_id); + return std::string(); + } + + std::string TestMulticast() { + int32_t socket_id = 0; + { + TestExtCompletionCallbackWithOutput<socket::CreateInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.Create( + socket::SocketType_Dev::UDP, Optional<socket::CreateOptions_Dev>(), + callback.GetCallback())); + if (callback.result() != PP_OK) + return "Create(): failed."; + socket_id = callback.output().socket_id(); + if (socket_id <= 0) + return "Create(): invalid socket ID."; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.SetMulticastTimeToLive( + socket_id, 0, callback.GetCallback())); + if (callback.result() != PP_OK || callback.output() != 0) + return "SetMulticastTimeToLive(): failed."; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.SetMulticastTimeToLive( + socket_id, -3, callback.GetCallback())); + if (callback.result() == PP_OK) + return "SetMulticastTimeToLive(): succeeded unexpectedly."; + if (callback.output() != -4) + return "SetMulticastTimeToLive(): returned unexpected result."; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.SetMulticastLoopbackMode( + socket_id, false, callback.GetCallback())); + if (callback.result() != PP_OK || callback.output() != 0) + return "SetMulticastLoopbackMode(): failed."; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.SetMulticastLoopbackMode( + socket_id, true, callback.GetCallback())); + if (callback.result() != PP_OK || callback.output() != 0) + return "SetMulticastLoopbackMode(): failed."; + } + + socket_.Destroy(socket_id); + socket_id = 0; + + int32_t server_socket_id = 0; + { + TestExtCompletionCallbackWithOutput<socket::CreateInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.Create( + socket::SocketType_Dev::UDP, Optional<socket::CreateOptions_Dev>(), + callback.GetCallback())); + if (callback.result() != PP_OK) + return "Create(): failed."; + server_socket_id = callback.output().socket_id(); + if (server_socket_id <= 0) + return "Create(): invalid socket ID."; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.Bind( + server_socket_id, "0.0.0.0", kMulticastPort, callback.GetCallback())); + if (callback.result() != PP_OK || callback.output() != 0) + return "Bind(): failed"; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.JoinGroup( + server_socket_id, kMulticastAddress, callback.GetCallback())); + if (callback.result() != PP_OK || callback.output() != 0) + return "JoinGroup(): failed."; + } + + { + TestExtCompletionCallbackWithOutput<std::vector<std::string> > + callback(pp_instance()); + callback.WaitForResult(socket_.GetJoinedGroups( + server_socket_id, callback.GetCallback())); + if (callback.result() != PP_OK) + return "GetJoinedGroups(): failed."; + std::vector<std::string> groups = callback.output(); + if (groups.size() != 1 || groups[0] != kMulticastAddress) { + return "GetJoinedGroups(): the returned groups didn't match those " + "joined."; + } + } + + int32_t client_socket_id = 0; + { + TestExtCompletionCallbackWithOutput<socket::CreateInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.Create( + socket::SocketType_Dev::UDP, Optional<socket::CreateOptions_Dev>(), + callback.GetCallback())); + if (callback.result() != PP_OK) + return "Create(): failed."; + client_socket_id = callback.output().socket_id(); + if (client_socket_id <= 0) + return "Create(): invalid socket ID."; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.SetMulticastTimeToLive( + client_socket_id, 0, callback.GetCallback())); + if (callback.result() != PP_OK || callback.output() != 0) + return "SetMulticastTimeToLive(): failed."; + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.Connect( + client_socket_id, kMulticastAddress, kMulticastPort, + callback.GetCallback())); + if (callback.result() != PP_OK || callback.output() != 0) + return "Connnect(): failed."; + } + + { + VarArrayBuffer input_array_buffer = + ConvertToArrayBuffer(kMulticastMessage); + size_t bytes_written = 0; + int32_t result_code = 0; + VarArrayBuffer data; + + TestExtCompletionCallbackWithOutput<socket::RecvFromInfo_Dev> + recv_from_callback(pp_instance()); + int32_t recv_from_result = socket_.RecvFrom( + server_socket_id, 1024, recv_from_callback.GetCallback()); + if (recv_from_result != PP_OK_COMPLETIONPENDING) + return "RecvFrom(): did not wait for data."; + + TestExtCompletionCallbackWithOutput<socket::WriteInfo_Dev> + write_callback(pp_instance()); + write_callback.WaitForResult(socket_.Write( + client_socket_id, input_array_buffer, write_callback.GetCallback())); + if (write_callback.result() != PP_OK) + return "Write(): failed."; + bytes_written = static_cast<size_t>( + write_callback.output().bytes_written()); + + recv_from_callback.WaitForResult(recv_from_result); + if (recv_from_callback.result() != PP_OK) + return "RecvFrom(): failed."; + socket::RecvFromInfo_Dev recv_from_info = recv_from_callback.output(); + result_code = recv_from_info.result_code(); + data = recv_from_info.data(); + + if (bytes_written != strlen(kMulticastMessage)) + return "Write(): did not send the whole data buffer."; + + if (result_code > 0 && + static_cast<uint32_t>(result_code) != data.ByteLength()) { + return "RecvFrom(): inconsistent result code and byte length."; + } + + std::string output_string = ConvertFromArrayBuffer(&data); + if (output_string != kMulticastMessage) { + return std::string("RecvFrom(): mismatched data: ").append( + output_string); + } + } + + { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.LeaveGroup( + server_socket_id, kMulticastAddress, callback.GetCallback())); + if (callback.result() != PP_OK || callback.output() != 0) + return "LeaveGroup(): failed."; + } + + socket_.Destroy(server_socket_id); + socket_.Destroy(client_socket_id); + return std::string(); + } + + std::string TestClientSocket() { + socket::SocketType_Dev socket_type; + if (!socket_type.Populate(Var(test_type_).pp_var())) + return "Invalid socket type."; + + int32_t socket_id = 0; + { + TestExtCompletionCallbackWithOutput<socket::CreateInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.Create( + socket_type, Optional<socket::CreateOptions_Dev>(), + callback.GetCallback())); + if (callback.result() != PP_OK) + return "Create(): failed."; + socket_id = callback.output().socket_id(); + if (socket_id <= 0) + return "Create(): invalid socket ID."; + } + + { + TestExtCompletionCallbackWithOutput<socket::SocketInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.GetInfo(socket_id, + callback.GetCallback())); + if (callback.result() != PP_OK) + return "GetInfo(): failed."; + + socket::SocketInfo_Dev socket_info = callback.output(); + if (socket_info.socket_type().value != socket_type.value) + return "GetInfo(): inconsistent socket type."; + if (socket_info.connected()) + return "GetInfo(): socket should not be connected."; + if (socket_info.peer_address().IsSet() || socket_info.peer_port().IsSet()) + return "GetInfo(): unconnected socket should not have peer."; + if (socket_info.local_address().IsSet() || + socket_info.local_port().IsSet()) { + return "GetInfo(): unconnected socket should not have local binding."; + } + } + + { + if (socket_type.value == socket::SocketType_Dev::TCP) { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.Connect( + socket_id, address_, port_, callback.GetCallback())); + if (callback.result() != PP_OK) + return "Connect(): failed."; + if (callback.output() != 0) + return "Connect(): failed."; + } else { + TestExtCompletionCallbackWithOutput<int32_t> callback(pp_instance()); + callback.WaitForResult(socket_.Bind( + socket_id, "0.0.0.0", 0, callback.GetCallback())); + if (callback.result() != PP_OK) + return "Bind(): failed."; + if (callback.output() != 0) + return "Bind(): failed."; + } + } + + { + TestExtCompletionCallbackWithOutput<socket::SocketInfo_Dev> + callback(pp_instance()); + callback.WaitForResult(socket_.GetInfo(socket_id, + callback.GetCallback())); + if (callback.result() != PP_OK) + return "GetInfo(): failed."; + + socket::SocketInfo_Dev socket_info = callback.output(); + if (socket_info.socket_type().value != socket_type.value) + return "GetInfo(): inconsistent socket type."; + if (!socket_info.local_address().IsSet() || + !socket_info.local_port().IsSet()) { + return "GetInfo(): bound socket should have local address and port."; + } + if (socket_type.value == socket::SocketType_Dev::TCP) { + if (!socket_info.connected()) + return "GetInfo(): TCP socket should be connected."; + if (!socket_info.peer_address().IsSet() || + !socket_info.peer_port().IsSet()) { + return "GetInfo(): connected TCP socket should have peer address and " + "port"; + } + if (*socket_info.peer_address() != "127.0.0.1" || + *socket_info.peer_port() != port_) { + return "GetInfo(): peer address and port should match the listening " + "server."; + } + } else { + if (socket_info.connected()) + return "GetInfo(): UDP socket should not be connected."; + if (socket_info.peer_address().IsSet() || + socket_info.peer_port().IsSet()) { + return "GetInfo(): unconnected UDP socket should not have peer " + "address or port."; + } + } + } + + { + TestExtCompletionCallbackWithOutput<bool> callback(pp_instance()); + callback.WaitForResult(socket_.SetNoDelay( + socket_id, true, callback.GetCallback())); + if (callback.result() != PP_OK) + return "SetNoDelay(): failed."; + if (socket_type.value == socket::SocketType_Dev::TCP) { + if (!callback.output()) + return "SetNoDelay(): failed for TCP."; + } else { + if (callback.output()) + return "SetNoDelay(): did not fail for UDP."; + } + } + + { + TestExtCompletionCallbackWithOutput<bool> callback(pp_instance()); + callback.WaitForResult(socket_.SetKeepAlive( + socket_id, true, 1000, callback.GetCallback())); + if (callback.result() != PP_OK) + return "SetKeepAlive(): failed."; + if (socket_type.value == socket::SocketType_Dev::TCP) { + if (!callback.output()) + return "SetKeepAlive(): failed for TCP."; + } else { + if (callback.output()) + return "SetKeepAlive(): did not fail for UDP."; + } + } + + { + VarArrayBuffer input_array_buffer = ConvertToArrayBuffer(kSendContents); + size_t bytes_written = 0; + int32_t result_code = 0; + VarArrayBuffer data; + if (socket_type.value == socket::SocketType_Dev::TCP) { + TestExtCompletionCallbackWithOutput<socket::ReadInfo_Dev> + read_callback(pp_instance()); + int32_t read_result = socket_.Read(socket_id, Optional<int32_t>(), + read_callback.GetCallback()); + if (read_result != PP_OK_COMPLETIONPENDING) + return "Read(): did not wait for data."; + + TestExtCompletionCallbackWithOutput<socket::WriteInfo_Dev> + write_callback(pp_instance()); + write_callback.WaitForResult(socket_.Write( + socket_id, input_array_buffer, write_callback.GetCallback())); + if (write_callback.result() != PP_OK) + return "Write(): failed."; + bytes_written = static_cast<size_t>( + write_callback.output().bytes_written()); + + read_callback.WaitForResult(read_result); + if (read_callback.result() != PP_OK) + return "Read(): failed."; + socket::ReadInfo_Dev read_info = read_callback.output(); + result_code = read_info.result_code(), + data = read_info.data(); + } else { + TestExtCompletionCallbackWithOutput<socket::RecvFromInfo_Dev> + recv_from_callback(pp_instance()); + int32_t recv_from_result = socket_.RecvFrom( + socket_id, Optional<int32_t>(), recv_from_callback.GetCallback()); + if (recv_from_result != PP_OK_COMPLETIONPENDING) + return "RecvFrom(): did not wait for data."; + + TestExtCompletionCallbackWithOutput<socket::WriteInfo_Dev> + send_to_callback(pp_instance()); + send_to_callback.WaitForResult(socket_.SendTo( + socket_id, input_array_buffer, address_, port_, + send_to_callback.GetCallback())); + if (send_to_callback.result() != PP_OK) + return "SendTo(): failed."; + bytes_written = static_cast<size_t>( + send_to_callback.output().bytes_written()); + + recv_from_callback.WaitForResult(recv_from_result); + if (recv_from_callback.result() != PP_OK) + return "RecvFrom(): failed."; + socket::RecvFromInfo_Dev recv_from_info = recv_from_callback.output(); + result_code = recv_from_info.result_code(); + data = recv_from_info.data(); + } + + if (bytes_written != strlen(kSendContents)) + return "SendTo() or Write(): did not send the whole data buffer."; + + if (result_code > 0 && + static_cast<uint32_t>(result_code) != data.ByteLength()) { + return "Read() or RecvFrom(): inconsistent result code and byte " + "length."; + } + + std::string output_string = ConvertFromArrayBuffer(&data); + size_t prefix_len = strlen(kReceiveContentsPrefix); + if (output_string.size() != prefix_len + kReceiveContentsSuffixSize || + output_string.compare(0, prefix_len, kReceiveContentsPrefix) != 0) { + return std::string("Read() or RecvFrom(): mismatched data: ").append( + output_string); + } + } + + { + TestExtCompletionCallbackWithOutput< + std::vector<socket::NetworkInterface_Dev> > callback(pp_instance()); + callback.WaitForResult(socket_.GetNetworkList(callback.GetCallback())); + if (callback.result() != PP_OK) + return "GetNetworkList(): failed."; + if (callback.output().empty()) + return "GetNetworkList(): returned an empty list."; + } + + socket_.Destroy(socket_id); + return std::string(); + } + + void Log(PP_LogLevel level, const char* format, ...) { + va_list args; + va_start(args, format); + char buf[512]; + vsnprintf(buf, sizeof(buf) - 1, format, args); + buf[sizeof(buf) - 1] = '\0'; + va_end(args); + + Var value(buf); + console_interface_->Log(pp_instance(), level, value.pp_var()); + } + + void NotifyTestDone(const std::string& message) { + PostMessage(message); + } + + VarArrayBuffer ConvertToArrayBuffer(const std::string data) { + VarArrayBuffer array_buffer(data.size()); + memcpy(array_buffer.Map(), data.c_str(), data.size()); + array_buffer.Unmap(); + return array_buffer; + } + + std::string ConvertFromArrayBuffer(VarArrayBuffer* array_buffer) { + std::string result(static_cast<const char*>(array_buffer->Map()), + array_buffer->ByteLength()); + array_buffer->Unmap(); + return result; + } + + socket::Socket_Dev socket_; + const PPB_Console* console_interface_; + + std::string test_type_; + std::string address_; + int32_t port_; +}; + +class MyModule : public Module { + public: + MyModule() : Module() {} + virtual ~MyModule() {} + + virtual Instance* CreateInstance(PP_Instance instance) { + return new MyInstance(instance); + } +}; + +namespace pp { + +Module* CreateModule() { + return new MyModule(); +} + +} // namespace pp + |