// Copyright 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 "ppapi/tests/test_udp_socket.h"

#include <vector>

#include "ppapi/cpp/pass_ref.h"
#include "ppapi/cpp/tcp_socket.h"
#include "ppapi/cpp/udp_socket.h"
#include "ppapi/cpp/var.h"
#include "ppapi/tests/test_utils.h"
#include "ppapi/tests/testing_instance.h"

REGISTER_TEST_CASE(UDPSocket);

namespace {

const uint16_t kPortScanFrom = 1024;
const uint16_t kPortScanTo = 4096;

pp::NetAddress ReplacePort(const pp::InstanceHandle& instance,
                           const pp::NetAddress& addr,
                           uint16_t port) {
  switch (addr.GetFamily()) {
    case PP_NETADDRESS_FAMILY_IPV4: {
      PP_NetAddress_IPv4 ipv4_addr;
      if (!addr.DescribeAsIPv4Address(&ipv4_addr))
        break;
      ipv4_addr.port = ConvertToNetEndian16(port);
      return pp::NetAddress(instance, ipv4_addr);
    }
    case PP_NETADDRESS_FAMILY_IPV6: {
      PP_NetAddress_IPv6 ipv6_addr;
      if (!addr.DescribeAsIPv6Address(&ipv6_addr))
        break;
      ipv6_addr.port = ConvertToNetEndian16(port);
      return pp::NetAddress(instance, ipv6_addr);
    }
    default: {
      PP_NOTREACHED();
    }
  }
  return pp::NetAddress();
}

}  // namespace

TestUDPSocket::TestUDPSocket(TestingInstance* instance)
    : TestCase(instance),
      socket_interface_1_0_(NULL),
      socket_interface_1_1_(NULL) {
}

bool TestUDPSocket::Init() {
  bool tcp_socket_is_available = pp::TCPSocket::IsAvailable();
  if (!tcp_socket_is_available)
    instance_->AppendError("PPB_TCPSocket interface not available");

  bool udp_socket_is_available = pp::UDPSocket::IsAvailable();
  if (!udp_socket_is_available)
    instance_->AppendError("PPB_UDPSocket interface not available");

  bool net_address_is_available = pp::NetAddress::IsAvailable();
  if (!net_address_is_available)
    instance_->AppendError("PPB_NetAddress interface not available");

  std::string host;
  uint16_t port = 0;
  bool init_address =
      GetLocalHostPort(instance_->pp_instance(), &host, &port) &&
      ResolveHost(instance_->pp_instance(), host, port, &address_);
  if (!init_address)
    instance_->AppendError("Can't init address");

  socket_interface_1_0_ =
      static_cast<const PPB_UDPSocket_1_0*>(
          pp::Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_INTERFACE_1_0));
  if (!socket_interface_1_0_)
    instance_->AppendError("PPB_UDPSocket_1_0 interface not available");

  socket_interface_1_1_ =
      static_cast<const PPB_UDPSocket_1_1*>(
          pp::Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_INTERFACE_1_1));
  if (!socket_interface_1_1_)
    instance_->AppendError("PPB_UDPSocket_1_1 interface not available");

  return tcp_socket_is_available &&
      udp_socket_is_available &&
      net_address_is_available &&
      init_address &&
      CheckTestingInterface() &&
      EnsureRunningOverHTTP() &&
      socket_interface_1_0_ != NULL &&
      socket_interface_1_1_ != NULL;
}

void TestUDPSocket::RunTests(const std::string& filter) {
  RUN_CALLBACK_TEST(TestUDPSocket, ReadWrite, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, Broadcast, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, SetOption_1_0, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, SetOption_1_1, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, SetOption, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, ParallelSend, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, Multicast, filter);

  // Failure tests. Generally can only be run individually, since they require
  // specific socket failures to be injected into the UDP code.
  RUN_CALLBACK_TEST(TestUDPSocket, BindFails, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, SetBroadcastFails, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, SendToFails, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, ReadFails, filter);
}

std::string TestUDPSocket::GetLocalAddress(pp::NetAddress* address) {
  pp::TCPSocket socket(instance_);
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket.Connect(address_, callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());
  *address = socket.GetLocalAddress();
  ASSERT_NE(0, address->pp_resource());
  socket.Close();
  PASS();
}

std::string TestUDPSocket::SetBroadcastOptions(pp::UDPSocket* socket) {
  TestCompletionCallback callback_1(instance_->pp_instance(), callback_type());
  callback_1.WaitForResult(socket->SetOption(
      PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(true),
      callback_1.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback_1);
  ASSERT_EQ(PP_OK, callback_1.result());

  TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
  callback_2.WaitForResult(socket->SetOption(
      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback_2.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback_2);
  ASSERT_EQ(PP_OK, callback_2.result());

  PASS();
}

std::string TestUDPSocket::BindUDPSocket(pp::UDPSocket* socket,
                                         const pp::NetAddress& address) {
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket->Bind(address, callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());
  PASS();
}

std::string TestUDPSocket::LookupPortAndBindUDPSocket(
    pp::UDPSocket* socket,
    pp::NetAddress* address) {
  pp::NetAddress base_address;
  ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address));

  bool is_free_port_found = false;
  std::string ret;
  for (uint16_t port = kPortScanFrom; port < kPortScanTo; ++port) {
    pp::NetAddress new_address = ReplacePort(instance_, base_address, port);
    ASSERT_NE(0, new_address.pp_resource());
    ret = BindUDPSocket(socket, new_address);
    if (ret.empty()) {
      is_free_port_found = true;
      break;
    }
  }
  if (!is_free_port_found)
    return "Can't find available port (" + ret + ")";

  *address = socket->GetBoundAddress();
  ASSERT_NE(0, address->pp_resource());

  PASS();
}

std::string TestUDPSocket::ReadSocket(pp::UDPSocket* socket,
                                      pp::NetAddress* address,
                                      size_t size,
                                      std::string* message) {
  std::vector<char> buffer(size);
  TestCompletionCallbackWithOutput<pp::NetAddress> callback(
      instance_->pp_instance(), callback_type());
  callback.WaitForResult(
      socket->RecvFrom(&buffer[0], static_cast<int32_t>(size),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_FALSE(callback.result() < 0);
  ASSERT_EQ(size, static_cast<size_t>(callback.result()));
  *address = callback.output();
  message->assign(buffer.begin(), buffer.end());
  PASS();
}

std::string TestUDPSocket::PassMessage(pp::UDPSocket* target,
                                       pp::UDPSocket* source,
                                       const pp::NetAddress& target_address,
                                       const std::string& message,
                                       pp::NetAddress* recvfrom_address) {
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  int32_t rv = source->SendTo(message.c_str(),
                              static_cast<int32_t>(message.size()),
                              target_address,
                              callback.GetCallback());
  std::string str;
  ASSERT_SUBTEST_SUCCESS(ReadSocket(target, recvfrom_address, message.size(),
                                    &str));

  callback.WaitForResult(rv);
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_FALSE(callback.result() < 0);
  ASSERT_EQ(message.size(), static_cast<size_t>(callback.result()));
  ASSERT_EQ(message, str);
  PASS();
}

std::string TestUDPSocket::SetMulticastOptions(pp::UDPSocket* socket) {
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket->SetOption(
      PP_UDPSOCKET_OPTION_MULTICAST_LOOP, pp::Var(true),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket->SetOption(
      PP_UDPSOCKET_OPTION_MULTICAST_TTL, pp::Var(1), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  PASS();
}

std::string TestUDPSocket::TestReadWrite() {
  pp::UDPSocket server_socket(instance_), client_socket(instance_);
  pp::NetAddress server_address, client_address;

  ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&server_socket,
                                                    &server_address));
  ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&client_socket,
                                                    &client_address));
  const std::string message = "Simple message that will be sent via UDP";
  pp::NetAddress recvfrom_address;
  ASSERT_SUBTEST_SUCCESS(PassMessage(&server_socket, &client_socket,
                                     server_address, message,
                                     &recvfrom_address));
  ASSERT_TRUE(EqualNetAddress(recvfrom_address, client_address));

  server_socket.Close();
  client_socket.Close();

  if (server_socket.GetBoundAddress().pp_resource() != 0)
    return "PPB_UDPSocket::GetBoundAddress: expected failure";

  PASS();
}

std::string TestUDPSocket::TestBroadcast() {
  pp::UDPSocket server1(instance_), server2(instance_);

  ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server1));
  ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server2));

  PP_NetAddress_IPv4 any_ipv4_address = { 0, { 0, 0, 0, 0 } };
  pp::NetAddress any_address(instance_, any_ipv4_address);
  ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server1, any_address));
  // Fill port field of |server_address|.
  pp::NetAddress server_address = server1.GetBoundAddress();
  ASSERT_NE(0, server_address.pp_resource());
  ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server2, server_address));

  PP_NetAddress_IPv4 server_ipv4_address;
  ASSERT_TRUE(server_address.DescribeAsIPv4Address(&server_ipv4_address));

  PP_NetAddress_IPv4 broadcast_ipv4_address = {
    server_ipv4_address.port, { 0xff, 0xff, 0xff, 0xff }
  };
  pp::NetAddress broadcast_address(instance_, broadcast_ipv4_address);

  std::string message;
  const std::string first_message = "first message";
  const std::string second_message = "second_message";

  pp::NetAddress recvfrom_address;
  ASSERT_SUBTEST_SUCCESS(PassMessage(&server1, &server2, broadcast_address,
                                     first_message, &recvfrom_address));
  // |first_message| was also received by |server2|.
  ASSERT_SUBTEST_SUCCESS(ReadSocket(&server2, &recvfrom_address,
                                    first_message.size(), &message));
  ASSERT_EQ(first_message, message);

  ASSERT_SUBTEST_SUCCESS(PassMessage(&server2, &server1, broadcast_address,
                                     second_message, &recvfrom_address));
  // |second_message| was also received by |server1|.
  ASSERT_SUBTEST_SUCCESS(ReadSocket(&server1, &recvfrom_address,
                                    second_message.size(), &message));
  ASSERT_EQ(second_message, message);

  server1.Close();
  server2.Close();
  PASS();
}

int32_t TestUDPSocket::SetOptionValue(UDPSocketSetOption func,
                                      PP_Resource socket,
                                      PP_UDPSocket_Option option,
                                      const PP_Var& value) {
  PP_TimeTicks start_time(NowInTimeTicks());
  TestCompletionCallback cb(instance_->pp_instance(), callback_type());
  cb.WaitForResult(func(socket, option, value,
                        cb.GetCallback().pp_completion_callback()));

  // Expanded from CHECK_CALLBACK_BEHAVIOR macro.
  if (cb.failed()) {
    std::string msg = MakeFailureMessage(__FILE__, __LINE__,
                                         cb.errors().c_str());

    instance_->LogTest("SetOptionValue", msg, start_time);
    return PP_ERROR_FAILED;
  }
  return cb.result();
}

std::string TestUDPSocket::TestSetOption_1_0() {
  PP_Resource socket = socket_interface_1_0_->Create(instance_->pp_instance());
  ASSERT_NE(0, socket);

  // Multicast options are not supported in interface 1.0.
  ASSERT_EQ(PP_ERROR_BADARGUMENT,
            SetOptionValue(socket_interface_1_0_->SetOption,
                           socket,
                           PP_UDPSOCKET_OPTION_MULTICAST_LOOP,
                           PP_MakeBool(PP_TRUE)));

  ASSERT_EQ(PP_ERROR_BADARGUMENT,
            SetOptionValue(socket_interface_1_0_->SetOption,
                           socket,
                           PP_UDPSOCKET_OPTION_MULTICAST_TTL,
                           PP_MakeInt32(1)));

  socket_interface_1_0_->Close(socket);
  pp::Module::Get()->core()->ReleaseResource(socket);

  PASS();
}

std::string TestUDPSocket::TestSetOption_1_1() {
  PP_Resource socket = socket_interface_1_1_->Create(instance_->pp_instance());
  ASSERT_NE(0, socket);

  // Multicast options are not supported in interface 1.1.
  ASSERT_EQ(PP_ERROR_BADARGUMENT,
            SetOptionValue(socket_interface_1_1_->SetOption,
                           socket,
                           PP_UDPSOCKET_OPTION_MULTICAST_LOOP,
                           PP_MakeBool(PP_TRUE)));

  ASSERT_EQ(PP_ERROR_BADARGUMENT,
            SetOptionValue(socket_interface_1_1_->SetOption,
                           socket,
                           PP_UDPSOCKET_OPTION_MULTICAST_TTL,
                           PP_MakeInt32(1)));

  socket_interface_1_1_->Close(socket);
  pp::Module::Get()->core()->ReleaseResource(socket);

  PASS();
}

std::string TestUDPSocket::TestSetOption() {
  pp::UDPSocket socket(instance_);

  ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&socket));
  ASSERT_SUBTEST_SUCCESS(SetMulticastOptions(&socket));

  // Try to pass incorrect option value's type.
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(1), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());

  // Invalid multicast TTL values (less than 0 and greater than 255).
  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_MULTICAST_TTL, pp::Var(-1), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_MULTICAST_TTL, pp::Var(256), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(false), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE, pp::Var(4096),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE, pp::Var(512),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  pp::NetAddress address;
  ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&socket, &address));

  // ADDRESS_REUSE won't take effect after the socket is bound.
  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(true),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_FAILED, callback.result());

  // BROADCAST, SEND_BUFFER_SIZE and RECV_BUFFER_SIZE can be set after the
  // socket is bound.
  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE, pp::Var(2048),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE, pp::Var(1024),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  PASS();
}

std::string TestUDPSocket::TestParallelSend() {
  // This test only makes sense when callbacks are optional.
  if (callback_type() != PP_OPTIONAL)
    PASS();

  pp::UDPSocket server_socket(instance_), client_socket(instance_);
  pp::NetAddress server_address, client_address;

  ASSERT_SUBTEST_SUCCESS(
      LookupPortAndBindUDPSocket(&server_socket, &server_address));
  ASSERT_SUBTEST_SUCCESS(
      LookupPortAndBindUDPSocket(&client_socket, &client_address));
  const std::string message = "Simple message that will be sent via UDP";
  pp::NetAddress recvfrom_address;

  const size_t kParallelSends = 10;
  std::vector<TestCompletionCallback*> sendto_callbacks(kParallelSends);
  std::vector<int32_t> sendto_results(kParallelSends);
  size_t pending = 0;
  for (size_t i = 0; i < kParallelSends; i++) {
    sendto_callbacks[i] =
        new TestCompletionCallback(instance_->pp_instance(), callback_type());
    sendto_results[i] =
        client_socket.SendTo(message.c_str(),
                             static_cast<int32_t>(message.size()),
                             server_address,
                             sendto_callbacks[i]->GetCallback());

    if (sendto_results[i] == PP_ERROR_INPROGRESS) {
      // Run a pending send to completion to free a slot for the current send.
      ASSERT_GT(i, pending);
      sendto_callbacks[pending]->WaitForResult(sendto_results[pending]);
      CHECK_CALLBACK_BEHAVIOR(*sendto_callbacks[pending]);
      ASSERT_EQ(message.size(),
                static_cast<size_t>(sendto_callbacks[pending]->result()));
      pending++;
      // Try to send the message again.
      sendto_results[i] =
          client_socket.SendTo(message.c_str(),
                               static_cast<int32_t>(message.size()),
                               server_address,
                               sendto_callbacks[i]->GetCallback());
      ASSERT_NE(PP_ERROR_INPROGRESS, sendto_results[i]);
    }
  }

  // Finish all pending sends.
  for (size_t i = pending; i < kParallelSends; i++) {
    sendto_callbacks[i]->WaitForResult(sendto_results[i]);
    CHECK_CALLBACK_BEHAVIOR(*sendto_callbacks[i]);
    ASSERT_EQ(message.size(),
              static_cast<size_t>(sendto_callbacks[i]->result()));
  }

  for (size_t i = 0; i < kParallelSends; ++i)
    delete sendto_callbacks[i];

  for (size_t i = 0; i < kParallelSends; i++) {
    std::string str;
    ASSERT_SUBTEST_SUCCESS(
        ReadSocket(&server_socket, &recvfrom_address, message.size(), &str));
    ASSERT_EQ(message, str);
  }

  server_socket.Close();
  client_socket.Close();

  PASS();
}

std::string TestUDPSocket::TestMulticast() {
  pp::UDPSocket server1(instance_), server2(instance_);

  ASSERT_SUBTEST_SUCCESS(SetMulticastOptions(&server1));
  ASSERT_SUBTEST_SUCCESS(SetMulticastOptions(&server2));

  server1.Close();
  server2.Close();

  PASS();
}

std::string TestUDPSocket::TestBindFails() {
  pp::UDPSocket socket(instance_);

  PP_NetAddress_IPv4 any_ipv4_address = {0, {0, 0, 0, 0}};
  pp::NetAddress any_address(instance_, any_ipv4_address);
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket.Bind(any_address, callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_FAILED, callback.result());
  PASS();
}

std::string TestUDPSocket::TestSetBroadcastFails() {
  pp::UDPSocket socket(instance_);
  PP_NetAddress_IPv4 any_ipv4_address = {0, {0, 0, 0, 0}};
  pp::NetAddress any_address(instance_, any_ipv4_address);
  ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&socket, any_address));

  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_FAILED, callback.result());

  // Setting broadcast again should also fail.
  TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
  callback_2.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback_2.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback_2);
  ASSERT_EQ(PP_ERROR_FAILED, callback_2.result());
  PASS();
}

std::string TestUDPSocket::TestSendToFails() {
  pp::UDPSocket socket(instance_);
  PP_NetAddress_IPv4 any_ipv4_address = {0, {0, 0, 0, 0}};
  pp::NetAddress any_address(instance_, any_ipv4_address);
  ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&socket, any_address));

  std::vector<char> buffer(1);
  buffer[0] = 1;
  PP_NetAddress_IPv4 target_ipv4_address = {1024, {127, 0, 0, 1}};
  pp::NetAddress target_address(instance_, target_ipv4_address);
  // All writes should fail.
  for (int i = 0; i < 10; ++i) {
    TestCompletionCallbackWithOutput<pp::NetAddress> callback(
        instance_->pp_instance(), callback_type());
    callback.WaitForResult(
        socket.SendTo(buffer.data(), static_cast<int32_t>(buffer.size()),
                      target_address, callback.GetCallback()));
    CHECK_CALLBACK_BEHAVIOR(callback);
    ASSERT_EQ(PP_ERROR_FAILED, callback.result());
  }
  PASS();
}

std::string TestUDPSocket::TestReadFails() {
  pp::UDPSocket socket(instance_);
  PP_NetAddress_IPv4 any_ipv4_address = {0, {0, 0, 0, 0}};
  pp::NetAddress any_address(instance_, any_ipv4_address);
  ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&socket, any_address));

  std::vector<char> buffer(1);
  // All reads should fail. Larger number of reads increases the chance that at
  // least one read will be synchronous.
  for (int i = 0; i < 200; ++i) {
    TestCompletionCallbackWithOutput<pp::NetAddress> callback(
        instance_->pp_instance(), callback_type());
    callback.WaitForResult(socket.RecvFrom(&buffer[0],
                                           static_cast<int32_t>(buffer.size()),
                                           callback.GetCallback()));
    CHECK_CALLBACK_BEHAVIOR(callback);
    ASSERT_EQ(PP_ERROR_FAILED, callback.result());
  }
  PASS();
}
