// Copyright 2018 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 <stddef.h>
#include <stdint.h>

#include <limits>
#include <utility>

#include "services/network/udp_socket.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/net_errors.h"
#include "net/socket/udp_socket.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/mojom/udp_socket.mojom.h"
#include "services/network/socket_factory.h"
#include "services/network/udp_socket_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace network {

namespace {

const size_t kDatagramSize = 255;

class SocketWrapperTestImpl : public UDPSocket::SocketWrapper {
 public:
  SocketWrapperTestImpl() {}
  ~SocketWrapperTestImpl() override {}

  int Connect(const net::IPEndPoint& remote_addr,
              mojom::UDPSocketOptionsPtr options,
              net::IPEndPoint* local_addr_out) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }
  int Bind(const net::IPEndPoint& local_addr,
           mojom::UDPSocketOptionsPtr options,
           net::IPEndPoint* local_addr_out) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }
  int SendTo(
      net::IOBuffer* buf,
      int buf_len,
      const net::IPEndPoint& dest_addr,
      net::CompletionOnceCallback callback,
      const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }
  int SetBroadcast(bool broadcast) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }
  int SetSendBufferSize(int send_buffer_size) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }
  int SetReceiveBufferSize(int receive_buffer_size) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }
  int JoinGroup(const net::IPAddress& group_address) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }
  int LeaveGroup(const net::IPAddress& group_address) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }
  int Write(
      net::IOBuffer* buf,
      int buf_len,
      net::CompletionOnceCallback callback,
      const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }
  int RecvFrom(net::IOBuffer* buf,
               int buf_len,
               net::IPEndPoint* address,
               net::CompletionOnceCallback callback) override {
    NOTREACHED();
    return net::ERR_NOT_IMPLEMENTED;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(SocketWrapperTestImpl);
};

net::IPEndPoint GetLocalHostWithAnyPort() {
  return net::IPEndPoint(net::IPAddress(127, 0, 0, 1), 0);
}

std::vector<uint8_t> CreateTestMessage(uint8_t initial, size_t size) {
  std::vector<uint8_t> array(size);
  for (size_t i = 0; i < size; ++i)
    array[i] = static_cast<uint8_t>((i + initial) % 256);
  return array;
}

// A Mock UDPSocket that always returns net::ERR_IO_PENDING for SendTo()s.
class HangingUDPSocket : public SocketWrapperTestImpl {
 public:
  HangingUDPSocket() {}

  // SocketWrapperTestImpl implementation.
  int Bind(const net::IPEndPoint& local_addr,
           mojom::UDPSocketOptionsPtr options,
           net::IPEndPoint* local_addr_out) override {
    return net::OK;
  }
  int SendTo(
      net::IOBuffer* buf,
      int buf_len,
      const net::IPEndPoint& address,
      net::CompletionOnceCallback callback,
      const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
    EXPECT_EQ(expected_data_,
              std::vector<unsigned char>(buf->data(), buf->data() + buf_len));
    if (should_complete_requests_)
      return net::OK;
    pending_io_buffers_.push_back(buf);
    pending_io_buffer_lengths_.push_back(buf_len);
    pending_send_requests_.push_back(std::move(callback));
    return net::ERR_IO_PENDING;
  }

  void set_expected_data(std::vector<uint8_t> expected_data) {
    expected_data_ = expected_data;
  }

  const std::vector<net::IOBuffer*>& pending_io_buffers() const {
    return pending_io_buffers_;
  }

  const std::vector<int>& pending_io_buffer_lengths() const {
    return pending_io_buffer_lengths_;
  }

  // Completes all pending requests.
  void CompleteAllPendingRequests() {
    should_complete_requests_ = true;
    for (auto& request : pending_send_requests_) {
      std::move(request).Run(net::OK);
    }
    pending_send_requests_.clear();
  }

 private:
  std::vector<uint8_t> expected_data_;
  bool should_complete_requests_ = false;
  std::vector<net::IOBuffer*> pending_io_buffers_;
  std::vector<int> pending_io_buffer_lengths_;
  std::vector<net::CompletionOnceCallback> pending_send_requests_;
};

// A Mock UDPSocket that returns 0 byte read.
class ZeroByteReadUDPSocket : public SocketWrapperTestImpl {
 public:
  ZeroByteReadUDPSocket() {}
  int Bind(const net::IPEndPoint& local_addr,
           mojom::UDPSocketOptionsPtr options,
           net::IPEndPoint* local_addr_out) override {
    return net::OK;
  }
  int RecvFrom(net::IOBuffer* buf,
               int buf_len,
               net::IPEndPoint* address,
               net::CompletionOnceCallback callback) override {
    *address = GetLocalHostWithAnyPort();
    return 0;
  }
};

}  // namespace

class UDPSocketTest : public testing::Test {
 public:
  UDPSocketTest()
      : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
        factory_(nullptr /*netlog*/, &url_request_context_) {}
  ~UDPSocketTest() override {}

  void SetWrappedSocket(
      UDPSocket* socket,
      std::unique_ptr<UDPSocket::SocketWrapper> socket_wrapper) {
    socket->wrapped_socket_ = std::move(socket_wrapper);
  }

  uint32_t GetRemainingRecvSlots(UDPSocket* socket) {
    return socket->remaining_recv_slots_;
  }

  SocketFactory* factory() { return &factory_; }

 private:
  base::test::TaskEnvironment task_environment_;
  net::TestURLRequestContext url_request_context_;
  SocketFactory factory_;

  DISALLOW_COPY_AND_ASSIGN(UDPSocketTest);
};

TEST_F(UDPSocketTest, Settings) {
  mojo::Remote<mojom::UDPSocket> socket_remote;
  factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());
  net::IPEndPoint server_addr;
  net::IPEndPoint any_port(GetLocalHostWithAnyPort());

  test::UDPSocketTestHelper helper(&socket_remote);
  net::IPEndPoint local_addr;
  mojom::UDPSocketOptionsPtr options = mojom::UDPSocketOptions::New();
  options->send_buffer_size = 1024;
  options->receive_buffer_size = 2048;
  ASSERT_EQ(net::OK,
            helper.BindSync(any_port, std::move(options), &local_addr));
  EXPECT_NE(local_addr.ToString(), any_port.ToString());
}

// Tests that Send() is used after Bind() is not supported. Send() should only
// be used after Connect().
TEST_F(UDPSocketTest, TestSendWithBind) {
  mojo::Remote<mojom::UDPSocket> socket_remote;
  factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());

  // Bind() the socket.
  test::UDPSocketTestHelper helper(&socket_remote);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  // Connect() has not been used, so Send() is not supported.
  std::vector<uint8_t> test_msg{1};
  int result = helper.SendSync(test_msg);
  EXPECT_EQ(net::ERR_UNEXPECTED, result);
}

// Tests that when SendTo() is used after Connect() is not supported. SendTo()
// should only be used after Bind().
TEST_F(UDPSocketTest, TestSendToWithConnect) {
  // Create a server socket to listen for incoming datagrams.
  test::UDPSocketListenerImpl listener;
  mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);

  mojo::Remote<mojom::UDPSocket> server_socket;
  factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
                             listener_receiver.BindNewPipeAndPassRemote());

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper helper(&server_socket);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  // Create a client socket to send datagrams.
  mojo::Remote<mojom::UDPSocket> client_socket;
  factory()->CreateUDPSocket(client_socket.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());
  net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper client_helper(&client_socket);
  ASSERT_EQ(net::OK,
            client_helper.ConnectSync(server_addr, nullptr, &client_addr));

  std::vector<uint8_t> test_msg({1});
  int result = client_helper.SendToSync(server_addr, test_msg);
  EXPECT_EQ(net::ERR_UNEXPECTED, result);
}

// TODO(crbug.com/1014916): These two tests are very flaky on Fuchsia.
#if defined(OS_FUCHSIA)
#define MAYBE_TestReadSendTo DISABLED_TestReadSendTo
#define MAYBE_TestUnexpectedSequences DISABLED_TestUnexpectedSequences
#else
#define MAYBE_TestReadSendTo TestReadSendTo
#define MAYBE_TestUnexpectedSequences TestUnexpectedSequences
#endif

// Tests that the sequence of calling Bind()/Connect() and setters is
// important.
TEST_F(UDPSocketTest, MAYBE_TestUnexpectedSequences) {
  mojo::Remote<mojom::UDPSocket> socket_remote;
  factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());
  test::UDPSocketTestHelper helper(&socket_remote);
  net::IPEndPoint local_addr(GetLocalHostWithAnyPort());

  // Now these Setters should not work before Bind().
  EXPECT_EQ(net::ERR_UNEXPECTED, helper.SetBroadcastSync(true));
  EXPECT_EQ(net::ERR_UNEXPECTED, helper.SetSendBufferSizeSync(4096));
  EXPECT_EQ(net::ERR_UNEXPECTED, helper.SetReceiveBufferSizeSync(4096));

  // Now Bind() the socket.
  ASSERT_EQ(net::OK, helper.BindSync(local_addr, nullptr, &local_addr));

  // Setting the buffer size should now succeed.
  EXPECT_EQ(net::OK, helper.SetSendBufferSizeSync(4096));
  EXPECT_EQ(net::OK, helper.SetReceiveBufferSizeSync(4096));

  // Calling Connect() after Bind() should fail because they can't be both used.
  ASSERT_EQ(net::ERR_SOCKET_IS_CONNECTED,
            helper.ConnectSync(local_addr, nullptr, &local_addr));

  // Now Close() the socket.
  socket_remote->Close();

  // Re-Bind() is okay.
  ASSERT_EQ(net::OK, helper.BindSync(local_addr, nullptr, &local_addr));
}

// Tests that if the underlying socket implementation's Send() returned
// ERR_IO_PENDING, udp_socket.cc doesn't free the send buffer.
TEST_F(UDPSocketTest, TestBufferValid) {
  mojo::Remote<mojom::UDPSocket> socket_remote;
  UDPSocket impl(mojo::NullRemote() /*listener*/, nullptr /*net_log*/);
  mojo::Receiver<mojom::UDPSocket> receiver(&impl);
  receiver.Bind(socket_remote.BindNewPipeAndPassReceiver());

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper helper(&socket_remote);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  HangingUDPSocket* socket_raw_ptr = new HangingUDPSocket();
  SetWrappedSocket(&impl, base::WrapUnique(socket_raw_ptr));

  std::vector<uint8_t> test_msg(CreateTestMessage(0, kDatagramSize));
  socket_raw_ptr->set_expected_data(test_msg);
  base::RunLoop run_loop;
  socket_remote->SendTo(
      GetLocalHostWithAnyPort(), test_msg,
      net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
      base::BindOnce(
          [](base::RunLoop* run_loop, int result) {
            EXPECT_EQ(net::OK, result);
            run_loop->Quit();
          },
          base::Unretained(&run_loop)));

  socket_remote.FlushForTesting();

  ASSERT_EQ(1u, socket_raw_ptr->pending_io_buffers().size());
  ASSERT_EQ(1u, socket_raw_ptr->pending_io_buffer_lengths().size());
  // Make sure the caller of HangingUDPSocket doesn't destroy the send buffer,
  // and that buffer still contains the exact same data.
  net::IOBuffer* buf = socket_raw_ptr->pending_io_buffers()[0];
  int buf_len = socket_raw_ptr->pending_io_buffer_lengths()[0];
  EXPECT_EQ(test_msg,
            std::vector<unsigned char>(buf->data(), buf->data() + buf_len));
}

// Test that exercises the queuing of send requests and makes sure
// ERR_INSUFFICIENT_RESOURCES is returned appropriately.
TEST_F(UDPSocketTest, TestInsufficientResources) {
  mojo::Remote<mojom::UDPSocket> socket_remote;
  UDPSocket impl(mojo::NullRemote() /*listener*/, nullptr /*net_log*/);
  mojo::Receiver<mojom::UDPSocket> receiver(&impl);
  receiver.Bind(socket_remote.BindNewPipeAndPassReceiver());

  const size_t kQueueSize = UDPSocket::kMaxPendingSendRequests;

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper helper(&socket_remote);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  HangingUDPSocket* socket_raw_ptr = new HangingUDPSocket();
  SetWrappedSocket(&impl, base::WrapUnique(socket_raw_ptr));

  std::vector<uint8_t> test_msg(CreateTestMessage(0, kDatagramSize));
  socket_raw_ptr->set_expected_data(test_msg);
  // Send |kQueueSize| + 1 datagrams in a row, so the queue is filled up.
  std::vector<std::unique_ptr<base::RunLoop>> run_loops;
  for (size_t i = 0; i < kQueueSize + 1; ++i) {
    run_loops.push_back(std::make_unique<base::RunLoop>());
    socket_remote->SendTo(
        GetLocalHostWithAnyPort(), test_msg,
        net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
        base::BindOnce(
            [](base::RunLoop* run_loop, int result) {
              EXPECT_EQ(net::OK, result);
              run_loop->Quit();
            },
            base::Unretained(run_loops[i].get())));
  }

  // SendTo() beyond the queue size should fail.
  EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES,
            helper.SendToSync(GetLocalHostWithAnyPort(), test_msg));

  // Complete all pending requests. Queued SendTo() should hear back.
  socket_raw_ptr->CompleteAllPendingRequests();
  for (const auto& loop : run_loops) {
    loop->Run();
  }
}

TEST_F(UDPSocketTest, TestReceiveMoreOverflow) {
  // Create a server socket to listen for incoming datagrams.
  test::UDPSocketListenerImpl listener;
  mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);

  mojo::Remote<mojom::UDPSocket> server_socket;
  UDPSocket impl(listener_receiver.BindNewPipeAndPassRemote(),
                 nullptr /*net_log*/);
  mojo::Receiver<mojom::UDPSocket> receiver(&impl);
  receiver.Bind(server_socket.BindNewPipeAndPassReceiver());

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper helper(&server_socket);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  server_socket->ReceiveMore(std::numeric_limits<uint32_t>::max());
  server_socket.FlushForTesting();
  EXPECT_EQ(std::numeric_limits<uint32_t>::max(), GetRemainingRecvSlots(&impl));
  server_socket->ReceiveMore(1);
  server_socket.FlushForTesting();
  EXPECT_EQ(std::numeric_limits<uint32_t>::max(), GetRemainingRecvSlots(&impl));
}

TEST_F(UDPSocketTest, TestReadSend) {
  // Create a server socket to listen for incoming datagrams.
  test::UDPSocketListenerImpl listener;
  mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);

  mojo::Remote<mojom::UDPSocket> server_socket;
  factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
                             listener_receiver.BindNewPipeAndPassRemote());

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper helper(&server_socket);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  // Create a client socket to send datagrams.
  mojo::Remote<mojom::UDPSocket> client_socket;
  factory()->CreateUDPSocket(client_socket.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());
  net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper client_helper(&client_socket);
  ASSERT_EQ(net::OK,
            client_helper.ConnectSync(server_addr, nullptr, &client_addr));

  const size_t kDatagramCount = 6;
  server_socket->ReceiveMore(kDatagramCount);

  for (size_t i = 0; i < kDatagramCount; ++i) {
    std::vector<uint8_t> test_msg(
        CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize));
    int result = client_helper.SendSync(test_msg);
    EXPECT_EQ(net::OK, result);
  }

  listener.WaitForReceivedResults(kDatagramCount);
  EXPECT_EQ(kDatagramCount, listener.results().size());

  int i = 0;
  for (const auto& result : listener.results()) {
    EXPECT_EQ(net::OK, result.net_error);
    EXPECT_EQ(result.src_addr, client_addr);
    EXPECT_EQ(CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize),
              result.data.value());
    i++;
  }
  // Tests that sending a message that is larger than the specified limit
  // results in an early rejection.
  std::vector<uint8_t> large_msg(64 * 1024, 1);
  EXPECT_EQ(net::ERR_MSG_TOO_BIG, helper.SendToSync(client_addr, large_msg));

  // Close and re-Connect client socket.
  client_socket->Close();
  client_socket.FlushForTesting();

  // Make sure datagram can still be sent from the re-connected client socket.
  ASSERT_EQ(net::OK,
            client_helper.ConnectSync(server_addr, nullptr, &client_addr));
  server_socket->ReceiveMore(1);
  std::vector<uint8_t> msg(CreateTestMessage(0, kDatagramSize));
  EXPECT_EQ(net::OK, client_helper.SendSync(msg));

  listener.WaitForReceivedResults(kDatagramCount + 1);
  ASSERT_EQ(kDatagramCount + 1, listener.results().size());

  auto result = listener.results()[kDatagramCount];
  EXPECT_EQ(net::OK, result.net_error);
  EXPECT_EQ(result.src_addr, client_addr);
  EXPECT_EQ(msg, result.data.value());
}

TEST_F(UDPSocketTest, MAYBE_TestReadSendTo) {
  // Create a server socket to send data.
  mojo::Remote<mojom::UDPSocket> server_socket;
  factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper helper(&server_socket);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  // Create a client socket to send datagrams.
  test::UDPSocketListenerImpl listener;
  mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);

  mojo::Remote<mojom::UDPSocket> client_socket;
  factory()->CreateUDPSocket(client_socket.BindNewPipeAndPassReceiver(),
                             listener_receiver.BindNewPipeAndPassRemote());
  net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper client_helper(&client_socket);
  ASSERT_EQ(net::OK,
            client_helper.ConnectSync(server_addr, nullptr, &client_addr));

  const size_t kDatagramCount = 6;
  client_socket->ReceiveMore(kDatagramCount);

  for (size_t i = 0; i < kDatagramCount; ++i) {
    std::vector<uint8_t> test_msg(
        CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize));
    int result = helper.SendToSync(client_addr, test_msg);
    EXPECT_EQ(net::OK, result);
  }

  listener.WaitForReceivedResults(kDatagramCount);
  EXPECT_EQ(kDatagramCount, listener.results().size());

  int i = 0;
  for (const auto& result : listener.results()) {
    EXPECT_EQ(net::OK, result.net_error);
    EXPECT_FALSE(result.src_addr);
    EXPECT_EQ(CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize),
              result.data.value());
    i++;
  }

  // Tests that sending a message that is larger than the specified limit
  // results in an early rejection.
  std::vector<uint8_t> large_msg(64 * 1024, 1);
  EXPECT_EQ(net::ERR_MSG_TOO_BIG, helper.SendToSync(client_addr, large_msg));

  // Make sure datagram can still be sent from the re-bound server socket.
  server_socket->Close();
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
  client_socket->ReceiveMore(1);
  std::vector<uint8_t> msg(CreateTestMessage(0, kDatagramSize));
  EXPECT_EQ(net::OK, helper.SendToSync(client_addr, msg));

  listener.WaitForReceivedResults(kDatagramCount + 1);
  ASSERT_EQ(kDatagramCount + 1, listener.results().size());

  auto result = listener.results()[kDatagramCount];
  EXPECT_EQ(net::OK, result.net_error);
  EXPECT_FALSE(result.src_addr);
  EXPECT_EQ(msg, result.data.value());
}

TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) {
  // Create a server socket to listen for incoming datagrams.
  test::UDPSocketListenerImpl listener;
  mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);

  mojo::Remote<mojom::UDPSocket> server_socket;
  factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
                             listener_receiver.BindNewPipeAndPassRemote());

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper helper(&server_socket);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  // Create a client socket to send datagrams.
  mojo::Remote<mojom::UDPSocket> client_socket;
  factory()->CreateUDPSocket(client_socket.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());
  net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper client_helper(&client_socket);
  ASSERT_EQ(net::OK,
            client_helper.ConnectSync(server_addr, nullptr, &client_addr));

  // Use a buffer size that is 1 byte smaller than the datagram size.
  // This should result in net::ERR_MSG_TOO_BIG, because the transport can't
  // complete the read with this small buffer size.
  size_t buffer_size = kDatagramSize - 1;
  server_socket->ReceiveMoreWithBufferSize(1, buffer_size);
  std::vector<uint8_t> test_msg(CreateTestMessage(0, kDatagramSize));
  ASSERT_EQ(net::OK, client_helper.SendSync(test_msg));

  listener.WaitForReceivedResults(1);
  ASSERT_EQ(1u, listener.results().size());
  auto result = listener.results()[0];
  EXPECT_EQ(net::ERR_MSG_TOO_BIG, result.net_error);
  EXPECT_FALSE(result.data);

  // Now use a buffer size that is equal to datagram size. This should be okay.
  server_socket->ReceiveMoreWithBufferSize(1, kDatagramSize);
  ASSERT_EQ(net::OK, client_helper.SendSync(test_msg));

  listener.WaitForReceivedResults(2);
  ASSERT_EQ(2u, listener.results().size());
  result = listener.results()[1];
  EXPECT_EQ(net::OK, result.net_error);
  EXPECT_EQ(client_addr, result.src_addr.value());
  EXPECT_EQ(test_msg, result.data.value());
}

// Make sure passing an invalid net::IPEndPoint will be detected by
// serialization/deserialization in mojo.
TEST_F(UDPSocketTest, TestSendToInvalidAddress) {
  mojo::Remote<mojom::UDPSocket> server_socket;
  factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper helper(&server_socket);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  std::vector<uint8_t> test_msg{1};
  std::vector<uint8_t> invalid_ip_addr{127, 0, 0, 0, 1};
  net::IPAddress ip_address(invalid_ip_addr.data(), invalid_ip_addr.size());
  EXPECT_FALSE(ip_address.IsValid());
  net::IPEndPoint invalid_addr(ip_address, 53);
  server_socket->SendTo(
      invalid_addr, test_msg,
      net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
      base::BindOnce([](int result) {}));
  // Make sure that the pipe is broken upon processing |invalid_addr|.
  base::RunLoop run_loop;
  server_socket.set_disconnect_handler(
      base::BindOnce([](base::RunLoop* run_loop) { run_loop->Quit(); },
                     base::Unretained(&run_loop)));
  run_loop.Run();
}

// Tests that it is legal for UDPSocketListener::OnReceive() to be called with
// 0 byte payload.
TEST_F(UDPSocketTest, TestReadZeroByte) {
  test::UDPSocketListenerImpl listener;
  mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);

  mojo::Remote<mojom::UDPSocket> socket_remote;
  UDPSocket impl(listener_receiver.BindNewPipeAndPassRemote(),
                 nullptr /*net_log*/);
  mojo::Receiver<mojom::UDPSocket> receiver(&impl);
  receiver.Bind(socket_remote.BindNewPipeAndPassReceiver());

  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  test::UDPSocketTestHelper helper(&socket_remote);
  ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));

  SetWrappedSocket(&impl, std::make_unique<ZeroByteReadUDPSocket>());

  socket_remote->ReceiveMore(1);

  listener.WaitForReceivedResults(1);
  ASSERT_EQ(1u, listener.results().size());

  auto result = listener.results()[0];
  EXPECT_EQ(net::OK, result.net_error);
  EXPECT_TRUE(result.data);
  EXPECT_EQ(std::vector<uint8_t>(), result.data.value());
}

#if defined(OS_ANDROID)
// Some Android devices do not support multicast socket.
// The ones supporting multicast need WifiManager.MulticastLock to enable it.
// https://developer.android.com/reference/android/net/wifi/WifiManager.MulticastLock.html
#define MAYBE_JoinMulticastGroup DISABLED_JoinMulticastGroup
#else
#define MAYBE_JoinMulticastGroup JoinMulticastGroup
#endif  // defined(OS_ANDROID)
TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) {
  const char kGroup[] = "237.132.100.17";

  net::IPAddress group_ip;
  EXPECT_TRUE(group_ip.AssignFromIPLiteral(kGroup));
  mojo::Remote<mojom::UDPSocket> socket_remote;
  test::UDPSocketListenerImpl listener;
  mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);
  factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
                             listener_receiver.BindNewPipeAndPassRemote());

  test::UDPSocketTestHelper helper(&socket_remote);

  mojom::UDPSocketOptionsPtr options = mojom::UDPSocketOptions::New();
#if defined(OS_FUCHSIA)
  // Fuchsia currently doesn't support automatic interface selection for
  // multicast, so interface index needs to be set explicitly.
  // See https://fuchsia.atlassian.net/browse/NET-195 .
  options->multicast_interface = 1;
#endif  // defined(OS_FUCHSIA)
  options->allow_address_sharing_for_multicast = true;

  net::IPAddress bind_ip_address;
  EXPECT_TRUE(bind_ip_address.AssignFromIPLiteral("0.0.0.0"));
  net::IPEndPoint socket_address(bind_ip_address, 0);
  ASSERT_EQ(net::OK, helper.BindSync(socket_address, std::move(options),
                                     &socket_address));
  int port = socket_address.port();
  EXPECT_NE(0, port);
  EXPECT_EQ(net::OK, helper.JoinGroupSync(group_ip));
  // Joining group multiple times.
  EXPECT_NE(net::OK, helper.JoinGroupSync(group_ip));

  // Receive messages from itself.
  std::vector<uint8_t> test_msg(CreateTestMessage(0, kDatagramSize));
  net::IPEndPoint group_alias(group_ip, port);
  EXPECT_EQ(net::OK, helper.SendToSync(group_alias, test_msg));
  socket_remote->ReceiveMore(1);
  listener.WaitForReceivedResults(1);
  ASSERT_EQ(1u, listener.results().size());
  auto result = listener.results()[0];
  EXPECT_EQ(net::OK, result.net_error);
  EXPECT_EQ(port, result.src_addr.value().port());
  EXPECT_EQ(test_msg, result.data.value());

  // Create a second socket to send a packet to multicast group.
  mojo::Remote<mojom::UDPSocket> second_socket_remote;
  factory()->CreateUDPSocket(second_socket_remote.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());
  test::UDPSocketTestHelper second_socket_helper(&second_socket_remote);
  net::IPEndPoint second_socket_address(bind_ip_address, 0);
  ASSERT_EQ(net::OK,
            second_socket_helper.BindSync(second_socket_address, nullptr,
                                          &second_socket_address));
  int second_port = second_socket_address.port();
  ASSERT_EQ(net::OK, second_socket_helper.SendToSync(group_alias, test_msg));

  // First socket should receive packet sent by the second socket.
  socket_remote->ReceiveMore(1);
  listener.WaitForReceivedResults(2);
  ASSERT_EQ(2u, listener.results().size());
  result = listener.results()[1];
  EXPECT_EQ(net::OK, result.net_error);
  EXPECT_EQ(second_port, result.src_addr.value().port());
  EXPECT_EQ(test_msg, result.data.value());

  // First socket leaves group multiple times.
  EXPECT_EQ(net::OK, helper.LeaveGroupSync(group_ip));
  EXPECT_NE(net::OK, helper.LeaveGroupSync(group_ip));

  // No longer can receive messages from itself or from second socket.
  EXPECT_EQ(net::OK, helper.SendToSync(group_alias, test_msg));
  ASSERT_EQ(net::OK, second_socket_helper.SendToSync(group_alias, test_msg));
  socket_remote->ReceiveMore(1);
  socket_remote.FlushForTesting();
  ASSERT_EQ(2u, listener.results().size());
}

TEST_F(UDPSocketTest, ErrorHappensDuringSocketOptionsConfiguration) {
  mojo::Remote<mojom::UDPSocket> server_socket_remote;
  factory()->CreateUDPSocket(server_socket_remote.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());
  test::UDPSocketTestHelper server_helper(&server_socket_remote);
  net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
  ASSERT_EQ(net::OK,
            server_helper.BindSync(server_addr, nullptr, &server_addr));

  mojo::Remote<mojom::UDPSocket> socket_remote;
  factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
                             mojo::NullRemote());
  test::UDPSocketTestHelper helper(&socket_remote);

  // Invalid options.
  mojom::UDPSocketOptionsPtr options = mojom::UDPSocketOptions::New();
  options->multicast_time_to_live = 256;

  net::IPEndPoint local_addr;
  ASSERT_EQ(net::ERR_INVALID_ARGUMENT,
            helper.ConnectSync(server_addr, std::move(options), &local_addr));

  // It's legal to retry Connect() with valid options.
  mojom::UDPSocketOptionsPtr valid_options = mojom::UDPSocketOptions::New();
  valid_options->multicast_time_to_live = 255;
  ASSERT_EQ(net::OK,
            helper.ConnectSync(server_addr, std::move(options), &local_addr));
  EXPECT_NE(0, local_addr.port());
}

}  // namespace network
