Chromium Code Reviews| Index: ppapi/tests/test_tcp_server_socket_private.cc |
| 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 0000000000000000000000000000000000000000..2113e7398b96f6f7ebdda1e0bb85e321c542f97a |
| --- /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; |
| + |
| +REGISTER_TEST_CASE(TCPServerSocketPrivate); |
| + |
| +TestTCPServerSocketPrivate::TestTCPServerSocketPrivate( |
| + TestingInstance* instance) |
| + : TestCase(instance), |
| + tcp_server_socket_private_interface_(NULL), |
| + tcp_socket_private_interface_(NULL), |
| + port_(0) { |
| +} |
| + |
| +bool TestTCPServerSocketPrivate::Init() { |
| + 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_) |
|
brettw
2012/02/09 00:13:48
Nit: need {}
ygorshenin1
2012/02/09 15:00:10
Done.
|
| + 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 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( |
| + uint16_t port, |
| + PP_NetAddress_Private* address) { |
| + TCPSocketPrivate socket(instance_); |
| + PP_NetAddress_Private local_address; |
| + |
| + 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(&local_address)) |
| + return ReportError("PPB_TCPSocket_Private::GetLocalAddress", 0); |
| + socket.Disconnect(); |
| + |
| + if (!NetAddressPrivate::ReplacePort(local_address, port, address)) |
| + return ReportError("PPB_NetAddress_Private::ReplacePort", 0); |
| + |
| + PASS(); |
| +} |
| + |
| +std::string TestTCPServerSocketPrivate::SyncCreate( |
| + PP_Instance instance, |
| + PP_Resource* tcp_server_socket) { |
| + TestCompletionCallback callback(instance, force_async_); |
| + int32_t rv = tcp_server_socket_private_interface_->Create( |
| + instance, tcp_server_socket, |
| + static_cast<pp::CompletionCallback>(callback).pp_completion_callback()); |
| + if (force_async_ && rv != PP_OK_COMPLETIONPENDING) |
| + return ReportError("PPB_TCPServerSocket_Private::Create force_async", rv); |
| + if (rv == PP_OK_COMPLETIONPENDING) |
| + rv = callback.WaitForResult(); |
| + ASSERT_EQ(PP_OK, rv); |
| + |
| + 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); |
|
yzshen1
2012/02/09 02:31:50
Is it possible that this will go on indefinitely w
ygorshenin1
2012/02/09 15:00:10
Alas, yes. If |server_socket| is in listening mode
|
| + } while (!error_message.empty()); |
| +} |
| + |
| +std::string TestTCPServerSocketPrivate::SyncListen(PP_Resource socket, |
| + uint16_t port, |
| + int32_t backlog) { |
| + PP_NetAddress_Private local_address; |
| + std::string error_message = GetLocalAddress(port, &local_address); |
| + ASSERT_SUCCESS(error_message); |
| + |
| + 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) |
| + return ReportError("PPB_TCPServerSocket_Private::Listen", rv); |
| + |
| + 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; |
|
yzshen1
2012/02/09 02:31:50
Please note that |server_socket| is leaked.
PP_Res
ygorshenin1
2012/02/09 15:00:10
Done.
|
| + std::string error_message; |
| + |
| + error_message = SyncCreate(0, &server_socket); |
| + if (error_message.empty()) |
| + return "Error: successful call of PPB_TCPServerSocket_Private::Create " \ |
| + " with 0 as instance"; |
| + |
| + error_message = SyncCreate(instance_->pp_instance(), &server_socket); |
| + ASSERT_SUCCESS(error_message); |
| + ASSERT_TRUE(server_socket != 0); |
| + ASSERT_TRUE(tcp_server_socket_private_interface_->IsTCPServerSocket( |
| + server_socket)); |
| + PASS(); |
| +} |
| + |
| +std::string TestTCPServerSocketPrivate::TestListen() { |
| + static const int kBacklog = 2; |
| + |
| + PP_Resource server_socket; |
| + std::string error_message = SyncCreate(instance_->pp_instance(), |
| + &server_socket); |
| + ASSERT_SUCCESS(error_message); |
| + ASSERT_TRUE(server_socket != 0); |
| + |
| + uint16_t local_port = force_async_ ? kLocalPortListenAsync : |
| + kLocalPortListenSync; |
| + |
| + error_message = SyncListen(server_socket, local_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(), local_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); |
| + |
| + PASS(); |
| +} |
| + |
| +std::string TestTCPServerSocketPrivate::TestBacklog() { |
| + static const size_t kBacklog = 5; |
| + |
| + PP_Resource server_socket; |
| + std::string error_message = SyncCreate(instance_->pp_instance(), |
| + &server_socket); |
| + ASSERT_SUCCESS(error_message); |
| + ASSERT_TRUE(server_socket != 0); |
| + |
| + uint16_t local_port = force_async_ ? kLocalPortBacklogAsync : |
| + kLocalPortBacklogSync; |
| + |
| + error_message = SyncListen(server_socket, local_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(), |
| + local_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]); |
| + |
| + 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); |
| + |
| + PASS(); |
| +} |