diff options
author | ygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-22 15:56:03 +0000 |
---|---|---|
committer | ygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-22 15:56:03 +0000 |
commit | 20e3112e65dd794b794bdabd53bc4542b767ad2d (patch) | |
tree | f84c170eab4600c7036af549039078eeb477a262 /ppapi/tests | |
parent | 11039d76fa14f1b007272144c0b300a19711532b (diff) | |
download | chromium_src-20e3112e65dd794b794bdabd53bc4542b767ad2d.zip chromium_src-20e3112e65dd794b794bdabd53bc4542b767ad2d.tar.gz chromium_src-20e3112e65dd794b794bdabd53bc4542b767ad2d.tar.bz2 |
Exposed Listen and Accept methods to in-process plugins.
BUG=108277
TEST=UI test TestTCPServerSocketPrivate
Review URL: http://codereview.chromium.org/9283022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@123033 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/tests')
-rw-r--r-- | ppapi/tests/test_tcp_server_socket_private.cc | 399 | ||||
-rw-r--r-- | ppapi/tests/test_tcp_server_socket_private.h | 56 |
2 files changed, 455 insertions, 0 deletions
diff --git a/ppapi/tests/test_tcp_server_socket_private.cc b/ppapi/tests/test_tcp_server_socket_private.cc new file mode 100644 index 0000000..47edda9 --- /dev/null +++ b/ppapi/tests/test_tcp_server_socket_private.cc @@ -0,0 +1,399 @@ +// Copyright (c) 2012 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 "ppapi/tests/test_tcp_server_socket_private.h" + +#include <cstddef> +#include <cstring> +#include <vector> + +#include "ppapi/cpp/module.h" +#include "ppapi/cpp/private/net_address_private.h" +#include "ppapi/cpp/private/tcp_socket_private.h" +#include "ppapi/tests/test_utils.h" +#include "ppapi/tests/testing_instance.h" + +#define ASSERT_SUCCESS(error_message) \ + if (!(error_message).empty()) \ + return (error_message); + +using pp::NetAddressPrivate; +using pp::TCPSocketPrivate; + +namespace { + +const uint16_t kPortScanFrom = 1024; +const uint16_t kPortScanTo = 4096; + +} // namespace + +REGISTER_TEST_CASE(TCPServerSocketPrivate); + +TestTCPServerSocketPrivate::TestTCPServerSocketPrivate( + TestingInstance* instance) + : TestCase(instance), + core_interface_(NULL), + tcp_server_socket_private_interface_(NULL), + tcp_socket_private_interface_(NULL), + port_(0) { +} + +bool TestTCPServerSocketPrivate::Init() { + core_interface_ = static_cast<const PPB_Core*>( + pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE)); + if (!core_interface_) + instance_->AppendError("PPB_Core interface not available"); + tcp_server_socket_private_interface_ = + static_cast<const PPB_TCPServerSocket_Private*>( + pp::Module::Get()->GetBrowserInterface( + PPB_TCPSERVERSOCKET_PRIVATE_INTERFACE)); + if (!tcp_server_socket_private_interface_) { + instance_->AppendError( + "PPB_TCPServerSocket_Private interface not available"); + } + + tcp_socket_private_interface_ = + static_cast<const PPB_TCPSocket_Private*>( + pp::Module::Get()->GetBrowserInterface( + PPB_TCPSOCKET_PRIVATE_INTERFACE)); + if (!tcp_socket_private_interface_) + instance_->AppendError("PPB_TCPSocket_Private interface not available"); + + bool tcp_socket_private_is_available = TCPSocketPrivate::IsAvailable(); + if (!tcp_socket_private_is_available) + instance_->AppendError("PPB_TCPSocket_Private interface not available"); + + bool net_address_private_is_available = NetAddressPrivate::IsAvailable(); + if (!net_address_private_is_available) + instance_->AppendError("PPB_NetAddress_Private interface not available"); + + bool init_host_port = GetLocalHostPort( + instance_->pp_instance(), &host_, &port_); + if (!init_host_port) + instance_->AppendError("Can't init host and port"); + + return core_interface_ && + tcp_server_socket_private_interface_ && + tcp_socket_private_is_available && + net_address_private_is_available && + init_host_port && + CheckTestingInterface(); +} + +void TestTCPServerSocketPrivate::RunTests(const std::string& filter) { + RUN_TEST_FORCEASYNC_AND_NOT(Create, filter); + RUN_TEST_FORCEASYNC_AND_NOT(Listen, filter); + RUN_TEST_FORCEASYNC_AND_NOT(Backlog, filter); +} + +std::string TestTCPServerSocketPrivate::GetLocalAddress( + PP_NetAddress_Private* address) { + TCPSocketPrivate socket(instance_); + + TestCompletionCallback callback(instance_->pp_instance(), force_async_); + int32_t rv = socket.Connect(host_.c_str(), port_, callback); + if (force_async_ && rv != PP_OK_COMPLETIONPENDING) + return ReportError("PPB_TCPSocket_Private::Connect force_async", rv); + if (rv == PP_OK_COMPLETIONPENDING) + rv = callback.WaitForResult(); + if (rv != PP_OK) + return ReportError("PPB_TCPSocket_Private::Connect", rv); + + if (!socket.GetLocalAddress(address)) + return ReportError("PPB_TCPSocket_Private::GetLocalAddress", 0); + socket.Disconnect(); + PASS(); +} + +std::string TestTCPServerSocketPrivate::SyncRead(PP_Resource socket, + char* buffer, + int32_t num_bytes) { + TestCompletionCallback callback(instance_->pp_instance(), force_async_); + + int32_t rv = tcp_socket_private_interface_->Read( + socket, buffer, num_bytes, + static_cast<pp::CompletionCallback>(callback).pp_completion_callback()); + + if (force_async_ && rv != PP_OK_COMPLETIONPENDING) + return ReportError("PPB_TCPSocket_Private::Read force_async", rv); + if (rv == PP_OK_COMPLETIONPENDING) + rv = callback.WaitForResult(); + + if (num_bytes != rv) + return ReportError("PPB_TCPSocket_Private::Read", rv); + + PASS(); +} + +std::string TestTCPServerSocketPrivate::SyncWrite(PP_Resource socket, + const char* buffer, + int32_t num_bytes) { + TestCompletionCallback callback(instance_->pp_instance(), force_async_); + int32_t rv = tcp_socket_private_interface_->Write( + socket, buffer, num_bytes, + static_cast<pp::CompletionCallback>(callback).pp_completion_callback()); + + if (force_async_ && rv != PP_OK_COMPLETIONPENDING) + return ReportError("PPB_TCPSocket_Private::Write force_async", rv); + if (rv == PP_OK_COMPLETIONPENDING) + rv = callback.WaitForResult(); + if (num_bytes != rv) + return ReportError("PPB_TCPSocket_Private::Write", rv); + + PASS(); +} + +std::string TestTCPServerSocketPrivate::SyncConnect(PP_Resource socket, + const char* host, + uint16_t port) { + TestCompletionCallback callback(instance_->pp_instance(), force_async_); + int32_t rv = tcp_socket_private_interface_->Connect( + socket, + host_.c_str(), + port, + static_cast<pp::CompletionCallback>(callback).pp_completion_callback()); + if (force_async_ && rv != PP_OK_COMPLETIONPENDING) + return ReportError("PPB_TCPSocket_Private::Connect force_async", rv); + if (rv == PP_OK_COMPLETIONPENDING) + rv = callback.WaitForResult(); + if (rv != PP_OK) + return ReportError("PPB_TCPSocket_Private::Connect", rv); + + PASS(); +} + +void TestTCPServerSocketPrivate::ForceConnect(PP_Resource socket, + const char* host, + uint16_t port) { + std::string error_message; + do { + error_message = SyncConnect(socket, host, port); + } while (!error_message.empty()); +} + +std::string TestTCPServerSocketPrivate::SyncListen(PP_Resource socket, + uint16_t* port, + int32_t backlog) { + PP_NetAddress_Private base_address, local_address; + std::string error_message = GetLocalAddress(&base_address); + ASSERT_SUCCESS(error_message); + + // TODO (ygorshenin): find more efficient way to select available + // ports. + bool is_free_port_found = false; + for (uint16_t p = kPortScanFrom; p < kPortScanTo; ++p) { + if (!NetAddressPrivate::ReplacePort(base_address, p, &local_address)) + return ReportError("PPB_NetAddress_Private::ReplacePort", 0); + + TestCompletionCallback callback(instance_->pp_instance(), force_async_); + int32_t rv = tcp_server_socket_private_interface_->Listen( + socket, + &local_address, + backlog, + static_cast<pp::CompletionCallback>(callback).pp_completion_callback()); + if (force_async_ && rv != PP_OK_COMPLETIONPENDING) + return ReportError("PPB_TCPServerSocket_Private::Listen force_async", rv); + if (rv == PP_OK_COMPLETIONPENDING) + rv = callback.WaitForResult(); + if (rv == PP_OK) { + *port = p; + is_free_port_found = true; + break; + } + } + + if (!is_free_port_found) + return "Can't find available port"; + PASS(); +} + +bool TestTCPServerSocketPrivate::IsSocketsConnected( + PP_Resource lhs, + PP_Resource rhs) { + PP_NetAddress_Private lhs_local_addr, lhs_remote_addr; + + if (!tcp_socket_private_interface_->GetLocalAddress(lhs, &lhs_local_addr)) + return false; + if (!tcp_socket_private_interface_->GetRemoteAddress(lhs, &lhs_remote_addr)) + return false; + + PP_NetAddress_Private rhs_local_addr, rhs_remote_addr; + if (!tcp_socket_private_interface_->GetLocalAddress(rhs, &rhs_local_addr)) + return false; + if (!tcp_socket_private_interface_->GetRemoteAddress(rhs, &rhs_remote_addr)) + return false; + + return NetAddressPrivate::AreEqual(lhs_local_addr, rhs_remote_addr) && + NetAddressPrivate::AreEqual(lhs_remote_addr, rhs_local_addr); +} + +std::string TestTCPServerSocketPrivate::SendMessage(PP_Resource dst, + PP_Resource src, + const char* message) { + const size_t message_size = strlen(message); + + std::string error_message = SyncWrite(src, message, message_size); + ASSERT_SUCCESS(error_message); + + std::vector<char> message_buffer(message_size); + error_message = SyncRead(dst, &message_buffer[0], message_size); + ASSERT_SUCCESS(error_message); + ASSERT_EQ(0, strncmp(message, &message_buffer[0], message_size)); + PASS(); +} + +std::string TestTCPServerSocketPrivate::TestConnectedSockets(PP_Resource lhs, + PP_Resource rhs) { + static const char* const kMessage = "simple message"; + std::string error_message = SendMessage(lhs, rhs, kMessage); + ASSERT_SUCCESS(error_message); + error_message = SendMessage(rhs, lhs, kMessage); + ASSERT_SUCCESS(error_message); + PASS(); +} + +std::string TestTCPServerSocketPrivate::TestCreate() { + PP_Resource server_socket; + + server_socket = tcp_server_socket_private_interface_->Create(0); + ASSERT_EQ(0, server_socket); + core_interface_->ReleaseResource(server_socket); + + server_socket = + tcp_server_socket_private_interface_->Create(instance_->pp_instance()); + ASSERT_TRUE(server_socket != 0); + ASSERT_TRUE(tcp_server_socket_private_interface_->IsTCPServerSocket( + server_socket)); + core_interface_->ReleaseResource(server_socket); + PASS(); +} + +std::string TestTCPServerSocketPrivate::TestListen() { + static const int kBacklog = 2; + + PP_Resource server_socket = + tcp_server_socket_private_interface_->Create(instance_->pp_instance()); + ASSERT_TRUE(server_socket != 0); + + uint16_t port; + std::string error_message = SyncListen(server_socket, &port, kBacklog); + ASSERT_SUCCESS(error_message); + + TestCompletionCallback accept_callback(instance_->pp_instance(), + force_async_); + PP_Resource accepted_socket; + int32_t accept_rv = tcp_server_socket_private_interface_->Accept( + server_socket, + &accepted_socket, + static_cast<pp::CompletionCallback>( + accept_callback).pp_completion_callback()); + + TCPSocketPrivate client_socket(instance_); + + ForceConnect(client_socket.pp_resource(), host_.c_str(), port); + + if (force_async_ && accept_rv != PP_OK_COMPLETIONPENDING) + return ReportError("PPB_TCPServerSocket_Private::Accept force_async", + accept_rv); + if (accept_rv == PP_OK_COMPLETIONPENDING) + accept_rv = accept_callback.WaitForResult(); + if (accept_rv != PP_OK) + return ReportError("PPB_TCPServerSocket_Private::Accept", accept_rv); + + ASSERT_TRUE(accepted_socket != 0); + ASSERT_TRUE(tcp_socket_private_interface_->IsTCPSocket(accepted_socket)); + + ASSERT_TRUE(IsSocketsConnected(client_socket.pp_resource(), accepted_socket)); + error_message = TestConnectedSockets(client_socket.pp_resource(), + accepted_socket); + ASSERT_SUCCESS(error_message); + + tcp_socket_private_interface_->Disconnect(accepted_socket); + client_socket.Disconnect(); + tcp_server_socket_private_interface_->StopListening(server_socket); + + core_interface_->ReleaseResource(accepted_socket); + core_interface_->ReleaseResource(server_socket); + PASS(); +} + +std::string TestTCPServerSocketPrivate::TestBacklog() { + static const size_t kBacklog = 5; + + PP_Resource server_socket = + tcp_server_socket_private_interface_->Create(instance_->pp_instance()); + ASSERT_TRUE(server_socket != 0); + + uint16_t port; + std::string error_message = SyncListen(server_socket, &port, 2 * kBacklog); + ASSERT_SUCCESS(error_message); + + std::vector<TCPSocketPrivate*> client_sockets(kBacklog); + std::vector<TestCompletionCallback*> connect_callbacks(kBacklog); + std::vector<int32_t> connect_rv(kBacklog); + for (size_t i = 0; i < kBacklog; ++i) { + client_sockets[i] = new TCPSocketPrivate(instance_); + connect_callbacks[i] = new TestCompletionCallback(instance_->pp_instance(), + force_async_); + connect_rv[i] = client_sockets[i]->Connect(host_.c_str(), + port, + *connect_callbacks[i]); + if (force_async_ && connect_rv[i] != PP_OK_COMPLETIONPENDING) + return ReportError("PPB_TCPSocket_Private::Connect force_async", + connect_rv[i]); + } + + std::vector<PP_Resource> accepted_sockets(kBacklog); + for (size_t i = 0; i < kBacklog; ++i) { + TestCompletionCallback callback(instance_->pp_instance(), force_async_); + int32_t rv = tcp_server_socket_private_interface_->Accept( + server_socket, + &accepted_sockets[i], + static_cast<pp::CompletionCallback>(callback).pp_completion_callback()); + if (force_async_ && rv != PP_OK_COMPLETIONPENDING) + return ReportError("PPB_TCPServerSocket_Private::Accept force_async", rv); + if (rv == PP_OK_COMPLETIONPENDING) + rv = callback.WaitForResult(); + if (rv != PP_OK) + return ReportError("PPB_TCPServerSocket_Private::Accept", rv); + + ASSERT_TRUE(accepted_sockets[i] != 0); + ASSERT_TRUE(tcp_socket_private_interface_->IsTCPSocket( + accepted_sockets[i])); + } + + for (size_t i = 0; i < kBacklog; ++i) { + if (connect_rv[i] == PP_OK_COMPLETIONPENDING) + connect_rv[i] = connect_callbacks[i]->WaitForResult(); + if (connect_rv[i] != PP_OK) + return ReportError("PPB_TCPSocket_Private::Connect", connect_rv[i]); + } + + for (size_t i = 0; i < kBacklog; ++i) { + bool found = false; + for (size_t j = 0; j < kBacklog && !found; ++j) + if (IsSocketsConnected(client_sockets[i]->pp_resource(), + accepted_sockets[j])) { + TestConnectedSockets(client_sockets[i]->pp_resource(), + accepted_sockets[j]); + found = true; + } + ASSERT_TRUE(found); + } + + for (size_t i = 0; i < kBacklog; ++i) { + tcp_socket_private_interface_->Disconnect(accepted_sockets[i]); + core_interface_->ReleaseResource(accepted_sockets[i]); + } + + for (size_t i = 0; i < kBacklog; ++i) { + client_sockets[i]->Disconnect(); + delete client_sockets[i]; + delete connect_callbacks[i]; + } + + tcp_server_socket_private_interface_->StopListening(server_socket); + core_interface_->ReleaseResource(server_socket); + PASS(); +} diff --git a/ppapi/tests/test_tcp_server_socket_private.h b/ppapi/tests/test_tcp_server_socket_private.h new file mode 100644 index 0000000..5ada1c1 --- /dev/null +++ b/ppapi/tests/test_tcp_server_socket_private.h @@ -0,0 +1,56 @@ +// Copyright (c) 2012 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. + +#ifndef PPAPI_TESTS_TEST_TCP_SERVER_SOCKET_PRIVATE_H_ +#define PPAPI_TESTS_TEST_TCP_SERVER_SOCKET_PRIVATE_H_ + +#include <string> + +#include "ppapi/c/pp_stdint.h" +#include "ppapi/c/ppb_core.h" +#include "ppapi/c/private/ppb_net_address_private.h" +#include "ppapi/c/private/ppb_tcp_server_socket_private.h" +#include "ppapi/c/private/ppb_tcp_socket_private.h" +#include "ppapi/tests/test_case.h" + +class TestTCPServerSocketPrivate : public TestCase { + public: + explicit TestTCPServerSocketPrivate(TestingInstance* instance); + + // TestCase implementation. + virtual bool Init(); + virtual void RunTests(const std::string& filter); + + private: + std::string GetLocalAddress(PP_NetAddress_Private* address); + std::string SyncRead(PP_Resource socket, char* buffer, int32_t num_bytes); + std::string SyncWrite(PP_Resource socket, + const char* buffer, + int32_t num_bytes); + std::string SyncConnect(PP_Resource socket, const char* host, uint16_t port); + void ForceConnect(PP_Resource socket, const char* host, uint16_t port); + std::string SyncListen(PP_Resource socket, uint16_t* port, int32_t backlog); + + bool IsSocketsConnected(PP_Resource lhs, PP_Resource rhs); + std::string SendMessage(PP_Resource dst, + PP_Resource src, + const char* message); + std::string TestConnectedSockets(PP_Resource lhs, PP_Resource rhs); + + std::string CheckIOOfConnectedSockets(PP_Resource src, PP_Resource dst); + std::string CheckAddressesOfConnectedSockets(PP_Resource lhs, + PP_Resource rhs); + + std::string TestCreate(); + std::string TestListen(); + std::string TestBacklog(); + + const PPB_Core* core_interface_; + const PPB_TCPServerSocket_Private* tcp_server_socket_private_interface_; + const PPB_TCPSocket_Private* tcp_socket_private_interface_; + std::string host_; + uint16_t port_; +}; + +#endif // PPAPI_TESTS_TEST_TCP_SERVER_SOCKET_PRIVATE_H_ |