123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- // 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 <cstdio>
- #include <vector>
- #include "ppapi/cpp/pass_ref.h"
- #include "ppapi/cpp/private/net_address_private.h"
- #include "ppapi/cpp/private/tcp_server_socket_private.h"
- #include "ppapi/cpp/private/tcp_socket_private.h"
- #include "ppapi/tests/test_utils.h"
- #include "ppapi/tests/testing_instance.h"
- using pp::NetAddressPrivate;
- using pp::TCPServerSocketPrivate;
- using pp::TCPSocketPrivate;
- namespace {
- // Used by pp::CompletionCallbacks that want to delete a PP_Resource, passed as
- // |user_data|, on completion.
- void DeleteResource(void* user_data, int32_t flags) {
- delete reinterpret_cast<PP_Resource*>(user_data);
- }
- } // namespace
- REGISTER_TEST_CASE(TCPServerSocketPrivate);
- TestTCPServerSocketPrivate::TestTCPServerSocketPrivate(
- TestingInstance* instance) : TestCase(instance) {
- }
- bool TestTCPServerSocketPrivate::Init() {
- bool tcp_server_socket_private_is_available =
- TCPServerSocketPrivate::IsAvailable();
- if (!tcp_server_socket_private_is_available) {
- instance_->AppendError(
- "PPB_TCPServerSocket_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_is_available &&
- tcp_socket_private_is_available &&
- net_address_private_is_available &&
- init_host_port &&
- CheckTestingInterface() &&
- EnsureRunningOverHTTP();
- }
- void TestTCPServerSocketPrivate::RunTests(const std::string& filter) {
- RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Listen, filter);
- RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Backlog, filter);
- RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, ListenFails, filter);
- RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, ListenHangs, filter);
- RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, AcceptFails, filter);
- RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, AcceptHangs, filter);
- }
- std::string TestTCPServerSocketPrivate::GetLocalAddress(
- PP_NetAddress_Private* address) {
- TCPSocketPrivate socket(instance_);
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(
- socket.Connect(host_.c_str(), port_, callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_OK, callback.result());
- ASSERT_TRUE(socket.GetLocalAddress(address));
- socket.Disconnect();
- PASS();
- }
- std::string TestTCPServerSocketPrivate::SyncRead(TCPSocketPrivate* socket,
- char* buffer,
- size_t num_bytes) {
- while (num_bytes > 0) {
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(
- socket->Read(buffer, static_cast<int32_t>(num_bytes),
- callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_TRUE(callback.result() >= 0);
- buffer += callback.result();
- num_bytes -= callback.result();
- }
- PASS();
- }
- std::string TestTCPServerSocketPrivate::SyncWrite(TCPSocketPrivate* socket,
- const char* buffer,
- size_t num_bytes) {
- while (num_bytes > 0) {
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(
- socket->Write(buffer, static_cast<int32_t>(num_bytes),
- callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_TRUE(callback.result() >= 0);
- buffer += callback.result();
- num_bytes -= callback.result();
- }
- PASS();
- }
- std::string TestTCPServerSocketPrivate::SyncConnect(
- TCPSocketPrivate* socket,
- PP_NetAddress_Private* address) {
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(
- socket->ConnectWithNetAddress(address, callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_OK, callback.result());
- PASS();
- }
- void TestTCPServerSocketPrivate::ForceConnect(TCPSocketPrivate* socket,
- PP_NetAddress_Private* address) {
- std::string error_message;
- do {
- error_message = SyncConnect(socket, address);
- } while (!error_message.empty());
- }
- std::string TestTCPServerSocketPrivate::SyncListenFails(
- pp::TCPServerSocketPrivate* socket) {
- uint8_t localhost_ip[4] = {127, 0, 0, 1};
- PP_NetAddress_Private ipv4;
- ASSERT_TRUE(
- NetAddressPrivate::CreateFromIPv4Address(localhost_ip, 80, &ipv4));
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(
- socket->Listen(&ipv4, 2 /* backlog */, callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_ERROR_FAILED, callback.result());
- PASS();
- }
- std::string TestTCPServerSocketPrivate::SyncAcceptFails(
- pp::TCPServerSocketPrivate* socket) {
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- PP_Resource resource;
- callback.WaitForResult(socket->Accept(&resource, callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_ERROR_FAILED, callback.result());
- PASS();
- }
- std::string TestTCPServerSocketPrivate::SyncListen(
- TCPServerSocketPrivate* socket,
- PP_NetAddress_Private* address,
- int32_t backlog) {
- PP_NetAddress_Private base_address;
- ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address));
- if (!NetAddressPrivate::ReplacePort(base_address, 0, address))
- return ReportError("PPB_NetAddress_Private::ReplacePort", 0);
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(
- socket->Listen(address, backlog, callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_OK, callback.result());
- int32_t rv = socket->GetLocalAddress(address);
- ASSERT_EQ(PP_OK, rv);
- ASSERT_TRUE(NetAddressPrivate::GetPort(*address) != 0);
- PASS();
- }
- std::string TestTCPServerSocketPrivate::TestListen() {
- static const int kBacklog = 2;
- TCPServerSocketPrivate server_socket(instance_);
- PP_NetAddress_Private address;
- ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket, &address, kBacklog));
- // We can't use a blocking callback for Accept, because it will wait forever
- // for the client to connect, since the client connects after.
- TestCompletionCallback accept_callback(instance_->pp_instance(), PP_REQUIRED);
- // We need to make sure there's a message loop to run accept_callback on.
- pp::MessageLoop current_thread_loop(pp::MessageLoop::GetCurrent());
- if (current_thread_loop.is_null() && testing_interface_->IsOutOfProcess()) {
- current_thread_loop = pp::MessageLoop(instance_);
- current_thread_loop.AttachToCurrentThread();
- }
- PP_Resource resource;
- int32_t accept_rv = server_socket.Accept(&resource,
- accept_callback.GetCallback());
- TCPSocketPrivate client_socket(instance_);
- ForceConnect(&client_socket, &address);
- PP_NetAddress_Private client_local_addr, client_remote_addr;
- ASSERT_TRUE(client_socket.GetLocalAddress(&client_local_addr));
- ASSERT_TRUE(client_socket.GetRemoteAddress(&client_remote_addr));
- accept_callback.WaitForResult(accept_rv);
- CHECK_CALLBACK_BEHAVIOR(accept_callback);
- ASSERT_EQ(PP_OK, accept_callback.result());
- ASSERT_TRUE(resource != 0);
- TCPSocketPrivate accepted_socket(pp::PassRef(), resource);
- PP_NetAddress_Private accepted_local_addr, accepted_remote_addr;
- ASSERT_TRUE(accepted_socket.GetLocalAddress(&accepted_local_addr));
- ASSERT_TRUE(accepted_socket.GetRemoteAddress(&accepted_remote_addr));
- ASSERT_TRUE(NetAddressPrivate::AreEqual(client_local_addr,
- accepted_remote_addr));
- const char kSentByte = 'a';
- ASSERT_SUBTEST_SUCCESS(SyncWrite(&client_socket,
- &kSentByte,
- sizeof(kSentByte)));
- char received_byte;
- ASSERT_SUBTEST_SUCCESS(SyncRead(&accepted_socket,
- &received_byte,
- sizeof(received_byte)));
- ASSERT_EQ(kSentByte, received_byte);
- accepted_socket.Disconnect();
- client_socket.Disconnect();
- server_socket.StopListening();
- PASS();
- }
- std::string TestTCPServerSocketPrivate::TestBacklog() {
- static const size_t kBacklog = 5;
- TCPServerSocketPrivate server_socket(instance_);
- PP_NetAddress_Private address;
- ASSERT_SUBTEST_SUCCESS(SyncListen(&server_socket, &address, 2 * kBacklog));
- 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(),
- callback_type());
- connect_rv[i] = client_sockets[i]->ConnectWithNetAddress(
- &address,
- connect_callbacks[i]->GetCallback());
- }
- std::vector<PP_Resource> resources(kBacklog);
- std::vector<TCPSocketPrivate*> accepted_sockets(kBacklog);
- for (size_t i = 0; i < kBacklog; ++i) {
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(
- server_socket.Accept(&resources[i], callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_OK, callback.result());
- ASSERT_TRUE(resources[i] != 0);
- accepted_sockets[i] = new TCPSocketPrivate(pp::PassRef(), resources[i]);
- }
- for (size_t i = 0; i < kBacklog; ++i) {
- connect_callbacks[i]->WaitForResult(connect_rv[i]);
- CHECK_CALLBACK_BEHAVIOR(*connect_callbacks[i]);
- ASSERT_EQ(PP_OK, connect_callbacks[i]->result());
- }
- for (size_t i = 0; i < kBacklog; ++i) {
- const char byte = static_cast<char>('a' + i);
- ASSERT_SUBTEST_SUCCESS(SyncWrite(client_sockets[i], &byte, sizeof(byte)));
- }
- bool byte_received[kBacklog] = {};
- for (size_t i = 0; i < kBacklog; ++i) {
- char byte;
- ASSERT_SUBTEST_SUCCESS(SyncRead(accepted_sockets[i], &byte, sizeof(byte)));
- const size_t index = byte - 'a';
- ASSERT_FALSE(byte_received[index]);
- byte_received[index] = true;
- }
- for (size_t i = 0; i < kBacklog; ++i) {
- client_sockets[i]->Disconnect();
- delete client_sockets[i];
- delete connect_callbacks[i];
- accepted_sockets[i]->Disconnect();
- delete accepted_sockets[i];
- }
- server_socket.StopListening();
- PASS();
- }
- std::string TestTCPServerSocketPrivate::TestListenFails() {
- TCPServerSocketPrivate socket(instance_);
- ASSERT_SUBTEST_SUCCESS(SyncListenFails(&socket));
- // After a listen failure, accept should fail, too.
- ASSERT_SUBTEST_SUCCESS(SyncAcceptFails(&socket));
- // Listening again fails, just because of the test fixture simulating another
- // failure.
- ASSERT_SUBTEST_SUCCESS(SyncListenFails(&socket));
- PASS();
- }
- std::string TestTCPServerSocketPrivate::TestListenHangs() {
- TCPServerSocketPrivate socket(instance_);
- uint8_t localhost_ip[4] = {127, 0, 0, 1};
- PP_NetAddress_Private ipv4;
- ASSERT_TRUE(
- NetAddressPrivate::CreateFromIPv4Address(localhost_ip, 80, &ipv4));
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- socket.Listen(&ipv4, 2 /* backlog */, DoNothingCallback());
- PASS();
- }
- std::string TestTCPServerSocketPrivate::TestAcceptFails() {
- TCPServerSocketPrivate socket(instance_);
- uint8_t localhost_ip[4] = {127, 0, 0, 1};
- PP_NetAddress_Private ipv4;
- ASSERT_TRUE(
- NetAddressPrivate::CreateFromIPv4Address(localhost_ip, 80, &ipv4));
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(
- socket.Listen(&ipv4, 2 /* backlog */, callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_OK, callback.result());
- // Accept calls should fail.
- ASSERT_SUBTEST_SUCCESS(SyncAcceptFails(&socket));
- ASSERT_SUBTEST_SUCCESS(SyncAcceptFails(&socket));
- // Listening again fails, since the socket is already listening.
- ASSERT_SUBTEST_SUCCESS(SyncListenFails(&socket));
- PASS();
- }
- std::string TestTCPServerSocketPrivate::TestAcceptHangs() {
- TCPServerSocketPrivate socket(instance_);
- uint8_t localhost_ip[4] = {127, 0, 0, 1};
- PP_NetAddress_Private ipv4;
- ASSERT_TRUE(
- NetAddressPrivate::CreateFromIPv4Address(localhost_ip, 80, &ipv4));
- TestCompletionCallback callback(instance_->pp_instance(), callback_type());
- callback.WaitForResult(
- socket.Listen(&ipv4, 2 /* backlog */, callback.GetCallback()));
- CHECK_CALLBACK_BEHAVIOR(callback);
- ASSERT_EQ(PP_OK, callback.result());
- PP_Resource* resource = new PP_Resource();
- socket.Accept(resource,
- pp::CompletionCallback(&DeleteResource, resource,
- PP_COMPLETIONCALLBACK_FLAG_OPTIONAL));
- PASS();
- }
|