summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
authorteravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-26 21:25:11 +0000
committerteravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-26 21:25:11 +0000
commit7d3b2545b5b449f1454e40a0865c8126bf4f119b (patch)
treeb35ffdd576e090ee37597bfe797d704e90761a89 /ppapi
parent6df1c805eaa6cbab95da9003357fafb416cba326 (diff)
downloadchromium_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.gyp33
-rw-r--r--ppapi/tests/extensions/socket/controller.js34
-rw-r--r--ppapi/tests/extensions/socket/index.html11
-rw-r--r--ppapi/tests/extensions/socket/main.js7
-rw-r--r--ppapi/tests/extensions/socket/manifest.json22
-rw-r--r--ppapi/tests/extensions/socket/test_socket.cc654
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
+