/*
 *  Copyright 2006 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <math.h>
#include <time.h>
#if defined(WEBRTC_POSIX)
#include <netinet/in.h>
#endif

#include <memory>

#include "webrtc/base/arraysize.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/ptr_util.h"
#include "webrtc/base/testclient.h"
#include "webrtc/base/testutils.h"
#include "webrtc/base/thread.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/base/virtualsocketserver.h"

using namespace rtc;

using webrtc::testing::SSE_CLOSE;
using webrtc::testing::SSE_ERROR;
using webrtc::testing::SSE_OPEN;
using webrtc::testing::SSE_READ;
using webrtc::testing::SSE_WRITE;
using webrtc::testing::StreamSink;

// Sends at a constant rate but with random packet sizes.
struct Sender : public MessageHandler {
  Sender(Thread* th, AsyncSocket* s, uint32_t rt)
      : thread(th),
        socket(MakeUnique<AsyncUDPSocket>(s)),
        done(false),
        rate(rt),
        count(0) {
    last_send = rtc::TimeMillis();
    thread->PostDelayed(RTC_FROM_HERE, NextDelay(), this, 1);
  }

  uint32_t NextDelay() {
    uint32_t size = (rand() % 4096) + 1;
    return 1000 * size / rate;
  }

  void OnMessage(Message* pmsg) {
    ASSERT_EQ(1u, pmsg->message_id);

    if (done)
      return;

    int64_t cur_time = rtc::TimeMillis();
    int64_t delay = cur_time - last_send;
    uint32_t size = static_cast<uint32_t>(rate * delay / 1000);
    size = std::min<uint32_t>(size, 4096);
    size = std::max<uint32_t>(size, sizeof(uint32_t));

    count += size;
    memcpy(dummy, &cur_time, sizeof(cur_time));
    socket->Send(dummy, size, options);

    last_send = cur_time;
    thread->PostDelayed(RTC_FROM_HERE, NextDelay(), this, 1);
  }

  Thread* thread;
  std::unique_ptr<AsyncUDPSocket> socket;
  rtc::PacketOptions options;
  bool done;
  uint32_t rate;  // bytes per second
  uint32_t count;
  int64_t last_send;
  char dummy[4096];
};

struct Receiver : public MessageHandler, public sigslot::has_slots<> {
  Receiver(Thread* th, AsyncSocket* s, uint32_t bw)
      : thread(th),
        socket(MakeUnique<AsyncUDPSocket>(s)),
        bandwidth(bw),
        done(false),
        count(0),
        sec_count(0),
        sum(0),
        sum_sq(0),
        samples(0) {
    socket->SignalReadPacket.connect(this, &Receiver::OnReadPacket);
    thread->PostDelayed(RTC_FROM_HERE, 1000, this, 1);
  }

  ~Receiver() {
    thread->Clear(this);
  }

  void OnReadPacket(AsyncPacketSocket* s, const char* data, size_t size,
                    const SocketAddress& remote_addr,
                    const PacketTime& packet_time) {
    ASSERT_EQ(socket.get(), s);
    ASSERT_GE(size, 4U);

    count += size;
    sec_count += size;

    uint32_t send_time = *reinterpret_cast<const uint32_t*>(data);
    uint32_t recv_time = rtc::TimeMillis();
    uint32_t delay = recv_time - send_time;
    sum += delay;
    sum_sq += delay * delay;
    samples += 1;
  }

  void OnMessage(Message* pmsg) {
    ASSERT_EQ(1u, pmsg->message_id);

    if (done)
      return;

    // It is always possible for us to receive more than expected because
    // packets can be further delayed in delivery.
    if (bandwidth > 0)
      ASSERT_TRUE(sec_count <= 5 * bandwidth / 4);
    sec_count = 0;
    thread->PostDelayed(RTC_FROM_HERE, 1000, this, 1);
  }

  Thread* thread;
  std::unique_ptr<AsyncUDPSocket> socket;
  uint32_t bandwidth;
  bool done;
  size_t count;
  size_t sec_count;
  double sum;
  double sum_sq;
  uint32_t samples;
};

class VirtualSocketServerTest : public testing::Test {
 public:
  VirtualSocketServerTest()
      : ss_(nullptr),
        thread_(&ss_),
        kIPv4AnyAddress(IPAddress(INADDR_ANY), 0),
        kIPv6AnyAddress(IPAddress(in6addr_any), 0) {}

  void CheckPortIncrementalization(const SocketAddress& post,
                                   const SocketAddress& pre) {
    EXPECT_EQ(post.port(), pre.port() + 1);
    IPAddress post_ip = post.ipaddr();
    IPAddress pre_ip = pre.ipaddr();
    EXPECT_EQ(pre_ip.family(), post_ip.family());
    if (post_ip.family() == AF_INET) {
      in_addr pre_ipv4 = pre_ip.ipv4_address();
      in_addr post_ipv4 = post_ip.ipv4_address();
      EXPECT_EQ(post_ipv4.s_addr, pre_ipv4.s_addr);
    } else if (post_ip.family() == AF_INET6) {
      in6_addr post_ip6 = post_ip.ipv6_address();
      in6_addr pre_ip6 = pre_ip.ipv6_address();
      uint32_t* post_as_ints = reinterpret_cast<uint32_t*>(&post_ip6.s6_addr);
      uint32_t* pre_as_ints = reinterpret_cast<uint32_t*>(&pre_ip6.s6_addr);
      EXPECT_EQ(post_as_ints[3], pre_as_ints[3]);
    }
  }

  // Test a client can bind to the any address, and all sent packets will have
  // the default route as the source address. Also, it can receive packets sent
  // to the default route.
  void TestDefaultRoute(const IPAddress& default_route) {
    ss_.SetDefaultRoute(default_route);

    // Create client1 bound to the any address.
    AsyncSocket* socket =
        ss_.CreateAsyncSocket(default_route.family(), SOCK_DGRAM);
    socket->Bind(EmptySocketAddressWithFamily(default_route.family()));
    SocketAddress client1_any_addr = socket->GetLocalAddress();
    EXPECT_TRUE(client1_any_addr.IsAnyIP());
    auto client1 = MakeUnique<TestClient>(MakeUnique<AsyncUDPSocket>(socket));

    // Create client2 bound to the default route.
    AsyncSocket* socket2 =
        ss_.CreateAsyncSocket(default_route.family(), SOCK_DGRAM);
    socket2->Bind(SocketAddress(default_route, 0));
    SocketAddress client2_addr = socket2->GetLocalAddress();
    EXPECT_FALSE(client2_addr.IsAnyIP());
    auto client2 = MakeUnique<TestClient>(MakeUnique<AsyncUDPSocket>(socket2));

    // Client1 sends to client2, client2 should see the default route as
    // client1's address.
    SocketAddress client1_addr;
    EXPECT_EQ(6, client1->SendTo("bizbaz", 6, client2_addr));
    EXPECT_TRUE(client2->CheckNextPacket("bizbaz", 6, &client1_addr));
    EXPECT_EQ(client1_addr,
              SocketAddress(default_route, client1_any_addr.port()));

    // Client2 can send back to client1's default route address.
    EXPECT_EQ(3, client2->SendTo("foo", 3, client1_addr));
    EXPECT_TRUE(client1->CheckNextPacket("foo", 3, &client2_addr));
  }

  void BasicTest(const SocketAddress& initial_addr) {
    AsyncSocket* socket =
        ss_.CreateAsyncSocket(initial_addr.family(), SOCK_DGRAM);
    socket->Bind(initial_addr);
    SocketAddress server_addr = socket->GetLocalAddress();
    // Make sure VSS didn't switch families on us.
    EXPECT_EQ(server_addr.family(), initial_addr.family());

    auto client1 = MakeUnique<TestClient>(MakeUnique<AsyncUDPSocket>(socket));
    AsyncSocket* socket2 =
        ss_.CreateAsyncSocket(initial_addr.family(), SOCK_DGRAM);
    auto client2 = MakeUnique<TestClient>(MakeUnique<AsyncUDPSocket>(socket2));

    SocketAddress client2_addr;
    EXPECT_EQ(3, client2->SendTo("foo", 3, server_addr));
    EXPECT_TRUE(client1->CheckNextPacket("foo", 3, &client2_addr));

    SocketAddress client1_addr;
    EXPECT_EQ(6, client1->SendTo("bizbaz", 6, client2_addr));
    EXPECT_TRUE(client2->CheckNextPacket("bizbaz", 6, &client1_addr));
    EXPECT_EQ(client1_addr, server_addr);

    SocketAddress empty = EmptySocketAddressWithFamily(initial_addr.family());
    for (int i = 0; i < 10; i++) {
      client2 = MakeUnique<TestClient>(
          WrapUnique(AsyncUDPSocket::Create(&ss_, empty)));

      SocketAddress next_client2_addr;
      EXPECT_EQ(3, client2->SendTo("foo", 3, server_addr));
      EXPECT_TRUE(client1->CheckNextPacket("foo", 3, &next_client2_addr));
      CheckPortIncrementalization(next_client2_addr, client2_addr);
      // EXPECT_EQ(next_client2_addr.port(), client2_addr.port() + 1);

      SocketAddress server_addr2;
      EXPECT_EQ(6, client1->SendTo("bizbaz", 6, next_client2_addr));
      EXPECT_TRUE(client2->CheckNextPacket("bizbaz", 6, &server_addr2));
      EXPECT_EQ(server_addr2, server_addr);

      client2_addr = next_client2_addr;
    }
  }

  // initial_addr should be made from either INADDR_ANY or in6addr_any.
  void ConnectTest(const SocketAddress& initial_addr) {
    StreamSink sink;
    SocketAddress accept_addr;
    const SocketAddress kEmptyAddr =
        EmptySocketAddressWithFamily(initial_addr.family());

    // Create client
    std::unique_ptr<AsyncSocket> client =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(client.get());
    EXPECT_EQ(client->GetState(), AsyncSocket::CS_CLOSED);
    EXPECT_TRUE(client->GetLocalAddress().IsNil());

    // Create server
    std::unique_ptr<AsyncSocket> server =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(server.get());
    EXPECT_NE(0, server->Listen(5));  // Bind required
    EXPECT_EQ(0, server->Bind(initial_addr));
    EXPECT_EQ(server->GetLocalAddress().family(), initial_addr.family());
    EXPECT_EQ(0, server->Listen(5));
    EXPECT_EQ(server->GetState(), AsyncSocket::CS_CONNECTING);

    // No pending server connections
    EXPECT_FALSE(sink.Check(server.get(), SSE_READ));
    EXPECT_TRUE(nullptr == server->Accept(&accept_addr));
    EXPECT_EQ(AF_UNSPEC, accept_addr.family());

    // Attempt connect to listening socket
    EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
    EXPECT_NE(client->GetLocalAddress(), kEmptyAddr);  // Implicit Bind
    EXPECT_NE(AF_UNSPEC, client->GetLocalAddress().family());  // Implicit Bind
    EXPECT_NE(client->GetLocalAddress(), server->GetLocalAddress());

    // Client is connecting
    EXPECT_EQ(client->GetState(), AsyncSocket::CS_CONNECTING);
    EXPECT_FALSE(sink.Check(client.get(), SSE_OPEN));
    EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));

    ss_.ProcessMessagesUntilIdle();

    // Client still connecting
    EXPECT_EQ(client->GetState(), AsyncSocket::CS_CONNECTING);
    EXPECT_FALSE(sink.Check(client.get(), SSE_OPEN));
    EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));

    // Server has pending connection
    EXPECT_TRUE(sink.Check(server.get(), SSE_READ));
    std::unique_ptr<Socket> accepted = WrapUnique(server->Accept(&accept_addr));
    EXPECT_TRUE(nullptr != accepted);
    EXPECT_NE(accept_addr, kEmptyAddr);
    EXPECT_EQ(accepted->GetRemoteAddress(), accept_addr);

    EXPECT_EQ(accepted->GetState(), AsyncSocket::CS_CONNECTED);
    EXPECT_EQ(accepted->GetLocalAddress(), server->GetLocalAddress());
    EXPECT_EQ(accepted->GetRemoteAddress(), client->GetLocalAddress());

    ss_.ProcessMessagesUntilIdle();

    // Client has connected
    EXPECT_EQ(client->GetState(), AsyncSocket::CS_CONNECTED);
    EXPECT_TRUE(sink.Check(client.get(), SSE_OPEN));
    EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
    EXPECT_EQ(client->GetRemoteAddress(), server->GetLocalAddress());
    EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
  }

  void ConnectToNonListenerTest(const SocketAddress& initial_addr) {
    StreamSink sink;
    SocketAddress accept_addr;
    const SocketAddress nil_addr;
    const SocketAddress empty_addr =
        EmptySocketAddressWithFamily(initial_addr.family());

    // Create client
    std::unique_ptr<AsyncSocket> client =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(client.get());

    // Create server
    std::unique_ptr<AsyncSocket> server =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(server.get());
    EXPECT_EQ(0, server->Bind(initial_addr));
    EXPECT_EQ(server->GetLocalAddress().family(), initial_addr.family());
    // Attempt connect to non-listening socket
    EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));

    ss_.ProcessMessagesUntilIdle();

    // No pending server connections
    EXPECT_FALSE(sink.Check(server.get(), SSE_READ));
    EXPECT_TRUE(nullptr == server->Accept(&accept_addr));
    EXPECT_EQ(accept_addr, nil_addr);

    // Connection failed
    EXPECT_EQ(client->GetState(), AsyncSocket::CS_CLOSED);
    EXPECT_FALSE(sink.Check(client.get(), SSE_OPEN));
    EXPECT_TRUE(sink.Check(client.get(), SSE_ERROR));
    EXPECT_EQ(client->GetRemoteAddress(), nil_addr);
  }

  void CloseDuringConnectTest(const SocketAddress& initial_addr) {
    StreamSink sink;
    SocketAddress accept_addr;
    const SocketAddress empty_addr =
        EmptySocketAddressWithFamily(initial_addr.family());

    // Create client and server
    std::unique_ptr<AsyncSocket> client(
        ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(client.get());
    std::unique_ptr<AsyncSocket> server(
        ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(server.get());

    // Initiate connect
    EXPECT_EQ(0, server->Bind(initial_addr));
    EXPECT_EQ(server->GetLocalAddress().family(), initial_addr.family());

    EXPECT_EQ(0, server->Listen(5));
    EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));

    // Server close before socket enters accept queue
    EXPECT_FALSE(sink.Check(server.get(), SSE_READ));
    server->Close();

    ss_.ProcessMessagesUntilIdle();

    // Result: connection failed
    EXPECT_EQ(client->GetState(), AsyncSocket::CS_CLOSED);
    EXPECT_TRUE(sink.Check(client.get(), SSE_ERROR));

    server.reset(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(server.get());

    // Initiate connect
    EXPECT_EQ(0, server->Bind(initial_addr));
    EXPECT_EQ(server->GetLocalAddress().family(), initial_addr.family());

    EXPECT_EQ(0, server->Listen(5));
    EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));

    ss_.ProcessMessagesUntilIdle();

    // Server close while socket is in accept queue
    EXPECT_TRUE(sink.Check(server.get(), SSE_READ));
    server->Close();

    ss_.ProcessMessagesUntilIdle();

    // Result: connection failed
    EXPECT_EQ(client->GetState(), AsyncSocket::CS_CLOSED);
    EXPECT_TRUE(sink.Check(client.get(), SSE_ERROR));

    // New server
    server.reset(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(server.get());

    // Initiate connect
    EXPECT_EQ(0, server->Bind(initial_addr));
    EXPECT_EQ(server->GetLocalAddress().family(), initial_addr.family());

    EXPECT_EQ(0, server->Listen(5));
    EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));

    ss_.ProcessMessagesUntilIdle();

    // Server accepts connection
    EXPECT_TRUE(sink.Check(server.get(), SSE_READ));
    std::unique_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
    ASSERT_TRUE(nullptr != accepted.get());
    sink.Monitor(accepted.get());

    // Client closes before connection complets
    EXPECT_EQ(accepted->GetState(), AsyncSocket::CS_CONNECTED);

    // Connected message has not been processed yet.
    EXPECT_EQ(client->GetState(), AsyncSocket::CS_CONNECTING);
    client->Close();

    ss_.ProcessMessagesUntilIdle();

    // Result: accepted socket closes
    EXPECT_EQ(accepted->GetState(), AsyncSocket::CS_CLOSED);
    EXPECT_TRUE(sink.Check(accepted.get(), SSE_CLOSE));
    EXPECT_FALSE(sink.Check(client.get(), SSE_CLOSE));
  }

  void CloseTest(const SocketAddress& initial_addr) {
    StreamSink sink;
    const SocketAddress kEmptyAddr;

    // Create clients
    std::unique_ptr<AsyncSocket> a =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(a.get());
    a->Bind(initial_addr);
    EXPECT_EQ(a->GetLocalAddress().family(), initial_addr.family());

    std::unique_ptr<AsyncSocket> b =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(b.get());
    b->Bind(initial_addr);
    EXPECT_EQ(b->GetLocalAddress().family(), initial_addr.family());

    EXPECT_EQ(0, a->Connect(b->GetLocalAddress()));
    EXPECT_EQ(0, b->Connect(a->GetLocalAddress()));

    ss_.ProcessMessagesUntilIdle();

    EXPECT_TRUE(sink.Check(a.get(), SSE_OPEN));
    EXPECT_EQ(a->GetState(), AsyncSocket::CS_CONNECTED);
    EXPECT_EQ(a->GetRemoteAddress(), b->GetLocalAddress());

    EXPECT_TRUE(sink.Check(b.get(), SSE_OPEN));
    EXPECT_EQ(b->GetState(), AsyncSocket::CS_CONNECTED);
    EXPECT_EQ(b->GetRemoteAddress(), a->GetLocalAddress());

    EXPECT_EQ(1, a->Send("a", 1));
    b->Close();
    EXPECT_EQ(1, a->Send("b", 1));

    ss_.ProcessMessagesUntilIdle();

    char buffer[10];
    EXPECT_FALSE(sink.Check(b.get(), SSE_READ));
    EXPECT_EQ(-1, b->Recv(buffer, 10, nullptr));

    EXPECT_TRUE(sink.Check(a.get(), SSE_CLOSE));
    EXPECT_EQ(a->GetState(), AsyncSocket::CS_CLOSED);
    EXPECT_EQ(a->GetRemoteAddress(), kEmptyAddr);

    // No signal for Closer
    EXPECT_FALSE(sink.Check(b.get(), SSE_CLOSE));
    EXPECT_EQ(b->GetState(), AsyncSocket::CS_CLOSED);
    EXPECT_EQ(b->GetRemoteAddress(), kEmptyAddr);
  }

  void TcpSendTest(const SocketAddress& initial_addr) {
    StreamSink sink;
    const SocketAddress kEmptyAddr;

    // Connect two sockets
    std::unique_ptr<AsyncSocket> a =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(a.get());
    a->Bind(initial_addr);
    EXPECT_EQ(a->GetLocalAddress().family(), initial_addr.family());

    std::unique_ptr<AsyncSocket> b =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    sink.Monitor(b.get());
    b->Bind(initial_addr);
    EXPECT_EQ(b->GetLocalAddress().family(), initial_addr.family());

    EXPECT_EQ(0, a->Connect(b->GetLocalAddress()));
    EXPECT_EQ(0, b->Connect(a->GetLocalAddress()));

    ss_.ProcessMessagesUntilIdle();

    const size_t kBufferSize = 2000;
    ss_.set_send_buffer_capacity(kBufferSize);
    ss_.set_recv_buffer_capacity(kBufferSize);

    const size_t kDataSize = 5000;
    char send_buffer[kDataSize], recv_buffer[kDataSize];
    for (size_t i = 0; i < kDataSize; ++i)
      send_buffer[i] = static_cast<char>(i % 256);
    memset(recv_buffer, 0, sizeof(recv_buffer));
    size_t send_pos = 0, recv_pos = 0;

    // Can't send more than send buffer in one write
    int result = a->Send(send_buffer + send_pos, kDataSize - send_pos);
    EXPECT_EQ(static_cast<int>(kBufferSize), result);
    send_pos += result;

    ss_.ProcessMessagesUntilIdle();
    EXPECT_FALSE(sink.Check(a.get(), SSE_WRITE));
    EXPECT_TRUE(sink.Check(b.get(), SSE_READ));

    // Receive buffer is already filled, fill send buffer again
    result = a->Send(send_buffer + send_pos, kDataSize - send_pos);
    EXPECT_EQ(static_cast<int>(kBufferSize), result);
    send_pos += result;

    ss_.ProcessMessagesUntilIdle();
    EXPECT_FALSE(sink.Check(a.get(), SSE_WRITE));
    EXPECT_FALSE(sink.Check(b.get(), SSE_READ));

    // No more room in send or receive buffer
    result = a->Send(send_buffer + send_pos, kDataSize - send_pos);
    EXPECT_EQ(-1, result);
    EXPECT_TRUE(a->IsBlocking());

    // Read a subset of the data
    result = b->Recv(recv_buffer + recv_pos, 500, nullptr);
    EXPECT_EQ(500, result);
    recv_pos += result;

    ss_.ProcessMessagesUntilIdle();
    EXPECT_TRUE(sink.Check(a.get(), SSE_WRITE));
    EXPECT_TRUE(sink.Check(b.get(), SSE_READ));

    // Room for more on the sending side
    result = a->Send(send_buffer + send_pos, kDataSize - send_pos);
    EXPECT_EQ(500, result);
    send_pos += result;

    // Empty the recv buffer
    while (true) {
      result = b->Recv(recv_buffer + recv_pos, kDataSize - recv_pos, nullptr);
      if (result < 0) {
        EXPECT_EQ(-1, result);
        EXPECT_TRUE(b->IsBlocking());
        break;
      }
      recv_pos += result;
    }

    ss_.ProcessMessagesUntilIdle();
    EXPECT_TRUE(sink.Check(b.get(), SSE_READ));

    // Continue to empty the recv buffer
    while (true) {
      result = b->Recv(recv_buffer + recv_pos, kDataSize - recv_pos, nullptr);
      if (result < 0) {
        EXPECT_EQ(-1, result);
        EXPECT_TRUE(b->IsBlocking());
        break;
      }
      recv_pos += result;
    }

    // Send last of the data
    result = a->Send(send_buffer + send_pos, kDataSize - send_pos);
    EXPECT_EQ(500, result);
    send_pos += result;

    ss_.ProcessMessagesUntilIdle();
    EXPECT_TRUE(sink.Check(b.get(), SSE_READ));

    // Receive the last of the data
    while (true) {
      result = b->Recv(recv_buffer + recv_pos, kDataSize - recv_pos, nullptr);
      if (result < 0) {
        EXPECT_EQ(-1, result);
        EXPECT_TRUE(b->IsBlocking());
        break;
      }
      recv_pos += result;
    }

    ss_.ProcessMessagesUntilIdle();
    EXPECT_FALSE(sink.Check(b.get(), SSE_READ));

    // The received data matches the sent data
    EXPECT_EQ(kDataSize, send_pos);
    EXPECT_EQ(kDataSize, recv_pos);
    EXPECT_EQ(0, memcmp(recv_buffer, send_buffer, kDataSize));
  }

  void TcpSendsPacketsInOrderTest(const SocketAddress& initial_addr) {
    const SocketAddress kEmptyAddr;

    // Connect two sockets
    std::unique_ptr<AsyncSocket> a =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    std::unique_ptr<AsyncSocket> b =
        WrapUnique(ss_.CreateAsyncSocket(initial_addr.family(), SOCK_STREAM));
    a->Bind(initial_addr);
    EXPECT_EQ(a->GetLocalAddress().family(), initial_addr.family());

    b->Bind(initial_addr);
    EXPECT_EQ(b->GetLocalAddress().family(), initial_addr.family());

    EXPECT_EQ(0, a->Connect(b->GetLocalAddress()));
    EXPECT_EQ(0, b->Connect(a->GetLocalAddress()));
    ss_.ProcessMessagesUntilIdle();

    // First, deliver all packets in 0 ms.
    char buffer[2] = { 0, 0 };
    const char cNumPackets = 10;
    for (char i = 0; i < cNumPackets; ++i) {
      buffer[0] = '0' + i;
      EXPECT_EQ(1, a->Send(buffer, 1));
    }

    ss_.ProcessMessagesUntilIdle();

    for (char i = 0; i < cNumPackets; ++i) {
      EXPECT_EQ(1, b->Recv(buffer, sizeof(buffer), nullptr));
      EXPECT_EQ(static_cast<char>('0' + i), buffer[0]);
    }

    // Next, deliver packets at random intervals
    const uint32_t mean = 50;
    const uint32_t stddev = 50;

    ss_.set_delay_mean(mean);
    ss_.set_delay_stddev(stddev);
    ss_.UpdateDelayDistribution();

    for (char i = 0; i < cNumPackets; ++i) {
      buffer[0] = 'A' + i;
      EXPECT_EQ(1, a->Send(buffer, 1));
    }

    ss_.ProcessMessagesUntilIdle();

    for (char i = 0; i < cNumPackets; ++i) {
      EXPECT_EQ(1, b->Recv(buffer, sizeof(buffer), nullptr));
      EXPECT_EQ(static_cast<char>('A' + i), buffer[0]);
    }
  }

  // It is important that initial_addr's port has to be 0 such that the
  // incremental port behavior could ensure the 2 Binds result in different
  // address.
  void BandwidthTest(const SocketAddress& initial_addr) {
    AsyncSocket* send_socket =
        ss_.CreateAsyncSocket(initial_addr.family(), SOCK_DGRAM);
    AsyncSocket* recv_socket =
        ss_.CreateAsyncSocket(initial_addr.family(), SOCK_DGRAM);
    ASSERT_EQ(0, send_socket->Bind(initial_addr));
    ASSERT_EQ(0, recv_socket->Bind(initial_addr));
    EXPECT_EQ(send_socket->GetLocalAddress().family(), initial_addr.family());
    EXPECT_EQ(recv_socket->GetLocalAddress().family(), initial_addr.family());
    ASSERT_EQ(0, send_socket->Connect(recv_socket->GetLocalAddress()));

    uint32_t bandwidth = 64 * 1024;
    ss_.set_bandwidth(bandwidth);

    Thread* pthMain = Thread::Current();
    Sender sender(pthMain, send_socket, 80 * 1024);
    Receiver receiver(pthMain, recv_socket, bandwidth);

    pthMain->ProcessMessages(5000);
    sender.done = true;
    pthMain->ProcessMessages(5000);

    ASSERT_TRUE(receiver.count >= 5 * 3 * bandwidth / 4);
    ASSERT_TRUE(receiver.count <= 6 * bandwidth);  // queue could drain for 1s

    ss_.set_bandwidth(0);
  }

  // It is important that initial_addr's port has to be 0 such that the
  // incremental port behavior could ensure the 2 Binds result in different
  // address.
  void DelayTest(const SocketAddress& initial_addr) {
    time_t seed = ::time(nullptr);
    LOG(LS_VERBOSE) << "seed = " << seed;
    srand(static_cast<unsigned int>(seed));

    const uint32_t mean = 2000;
    const uint32_t stddev = 500;

    ss_.set_delay_mean(mean);
    ss_.set_delay_stddev(stddev);
    ss_.UpdateDelayDistribution();

    AsyncSocket* send_socket =
        ss_.CreateAsyncSocket(initial_addr.family(), SOCK_DGRAM);
    AsyncSocket* recv_socket =
        ss_.CreateAsyncSocket(initial_addr.family(), SOCK_DGRAM);
    ASSERT_EQ(0, send_socket->Bind(initial_addr));
    ASSERT_EQ(0, recv_socket->Bind(initial_addr));
    EXPECT_EQ(send_socket->GetLocalAddress().family(), initial_addr.family());
    EXPECT_EQ(recv_socket->GetLocalAddress().family(), initial_addr.family());
    ASSERT_EQ(0, send_socket->Connect(recv_socket->GetLocalAddress()));

    Thread* pthMain = Thread::Current();
    // Avg packet size is 2K, so at 200KB/s for 10s, we should see about
    // 1000 packets, which is necessary to get a good distribution.
    Sender sender(pthMain, send_socket, 100 * 2 * 1024);
    Receiver receiver(pthMain, recv_socket, 0);

    pthMain->ProcessMessages(10000);
    sender.done = receiver.done = true;
    ss_.ProcessMessagesUntilIdle();

    const double sample_mean = receiver.sum / receiver.samples;
    double num =
        receiver.samples * receiver.sum_sq - receiver.sum * receiver.sum;
    double den = receiver.samples * (receiver.samples - 1);
    const double sample_stddev = sqrt(num / den);
    LOG(LS_VERBOSE) << "mean=" << sample_mean << " stddev=" << sample_stddev;

    EXPECT_LE(500u, receiver.samples);
    // We initially used a 0.1 fudge factor, but on the build machine, we
    // have seen the value differ by as much as 0.13.
    EXPECT_NEAR(mean, sample_mean, 0.15 * mean);
    EXPECT_NEAR(stddev, sample_stddev, 0.15 * stddev);

    ss_.set_delay_mean(0);
    ss_.set_delay_stddev(0);
    ss_.UpdateDelayDistribution();
  }

  // Test cross-family communication between a client bound to client_addr and a
  // server bound to server_addr. shouldSucceed indicates if communication is
  // expected to work or not.
  void CrossFamilyConnectionTest(const SocketAddress& client_addr,
                                 const SocketAddress& server_addr,
                                 bool shouldSucceed) {
    StreamSink sink;
    SocketAddress accept_address;
    const SocketAddress kEmptyAddr;

    // Client gets a IPv4 address
    std::unique_ptr<AsyncSocket> client =
        WrapUnique(ss_.CreateAsyncSocket(client_addr.family(), SOCK_STREAM));
    sink.Monitor(client.get());
    EXPECT_EQ(client->GetState(), AsyncSocket::CS_CLOSED);
    EXPECT_EQ(client->GetLocalAddress(), kEmptyAddr);
    client->Bind(client_addr);

    // Server gets a non-mapped non-any IPv6 address.
    // IPv4 sockets should not be able to connect to this.
    std::unique_ptr<AsyncSocket> server =
        WrapUnique(ss_.CreateAsyncSocket(server_addr.family(), SOCK_STREAM));
    sink.Monitor(server.get());
    server->Bind(server_addr);
    server->Listen(5);

    if (shouldSucceed) {
      EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
      ss_.ProcessMessagesUntilIdle();
      EXPECT_TRUE(sink.Check(server.get(), SSE_READ));
      std::unique_ptr<Socket> accepted =
          WrapUnique(server->Accept(&accept_address));
      EXPECT_TRUE(nullptr != accepted);
      EXPECT_NE(kEmptyAddr, accept_address);
      ss_.ProcessMessagesUntilIdle();
      EXPECT_TRUE(sink.Check(client.get(), SSE_OPEN));
      EXPECT_EQ(client->GetRemoteAddress(), server->GetLocalAddress());
    } else {
      // Check that the connection failed.
      EXPECT_EQ(-1, client->Connect(server->GetLocalAddress()));
      ss_.ProcessMessagesUntilIdle();

      EXPECT_FALSE(sink.Check(server.get(), SSE_READ));
      EXPECT_TRUE(nullptr == server->Accept(&accept_address));
      EXPECT_EQ(accept_address, kEmptyAddr);
      EXPECT_EQ(client->GetState(), AsyncSocket::CS_CLOSED);
      EXPECT_FALSE(sink.Check(client.get(), SSE_OPEN));
      EXPECT_EQ(client->GetRemoteAddress(), kEmptyAddr);
    }
  }

  // Test cross-family datagram sending between a client bound to client_addr
  // and a server bound to server_addr. shouldSucceed indicates if sending is
  // expected to succeed or not.
  void CrossFamilyDatagramTest(const SocketAddress& client_addr,
                               const SocketAddress& server_addr,
                               bool shouldSucceed) {
    AsyncSocket* socket = ss_.CreateAsyncSocket(SOCK_DGRAM);
    socket->Bind(server_addr);
    SocketAddress bound_server_addr = socket->GetLocalAddress();
    auto client1 = MakeUnique<TestClient>(MakeUnique<AsyncUDPSocket>(socket));

    AsyncSocket* socket2 = ss_.CreateAsyncSocket(SOCK_DGRAM);
    socket2->Bind(client_addr);
    auto client2 = MakeUnique<TestClient>(MakeUnique<AsyncUDPSocket>(socket2));
    SocketAddress client2_addr;

    if (shouldSucceed) {
      EXPECT_EQ(3, client2->SendTo("foo", 3, bound_server_addr));
      EXPECT_TRUE(client1->CheckNextPacket("foo", 3, &client2_addr));
      SocketAddress client1_addr;
      EXPECT_EQ(6, client1->SendTo("bizbaz", 6, client2_addr));
      EXPECT_TRUE(client2->CheckNextPacket("bizbaz", 6, &client1_addr));
      EXPECT_EQ(client1_addr, bound_server_addr);
    } else {
      EXPECT_EQ(-1, client2->SendTo("foo", 3, bound_server_addr));
      EXPECT_TRUE(client1->CheckNoPacket());
    }
  }

 protected:
  VirtualSocketServer ss_;
  AutoSocketServerThread thread_;
  const SocketAddress kIPv4AnyAddress;
  const SocketAddress kIPv6AnyAddress;
};

TEST_F(VirtualSocketServerTest, basic_v4) {
  SocketAddress ipv4_test_addr(IPAddress(INADDR_ANY), 5000);
  BasicTest(ipv4_test_addr);
}

TEST_F(VirtualSocketServerTest, basic_v6) {
  SocketAddress ipv6_test_addr(IPAddress(in6addr_any), 5000);
  BasicTest(ipv6_test_addr);
}

TEST_F(VirtualSocketServerTest, TestDefaultRoute_v4) {
  IPAddress ipv4_default_addr(0x01020304);
  TestDefaultRoute(ipv4_default_addr);
}

TEST_F(VirtualSocketServerTest, TestDefaultRoute_v6) {
  IPAddress ipv6_default_addr;
  EXPECT_TRUE(
      IPFromString("2401:fa00:4:1000:be30:5bff:fee5:c3", &ipv6_default_addr));
  TestDefaultRoute(ipv6_default_addr);
}

TEST_F(VirtualSocketServerTest, connect_v4) {
  ConnectTest(kIPv4AnyAddress);
}

TEST_F(VirtualSocketServerTest, connect_v6) {
  ConnectTest(kIPv6AnyAddress);
}

TEST_F(VirtualSocketServerTest, connect_to_non_listener_v4) {
  ConnectToNonListenerTest(kIPv4AnyAddress);
}

TEST_F(VirtualSocketServerTest, connect_to_non_listener_v6) {
  ConnectToNonListenerTest(kIPv6AnyAddress);
}

TEST_F(VirtualSocketServerTest, close_during_connect_v4) {
  CloseDuringConnectTest(kIPv4AnyAddress);
}

TEST_F(VirtualSocketServerTest, close_during_connect_v6) {
  CloseDuringConnectTest(kIPv6AnyAddress);
}

TEST_F(VirtualSocketServerTest, close_v4) {
  CloseTest(kIPv4AnyAddress);
}

TEST_F(VirtualSocketServerTest, close_v6) {
  CloseTest(kIPv6AnyAddress);
}

TEST_F(VirtualSocketServerTest, tcp_send_v4) {
  TcpSendTest(kIPv4AnyAddress);
}

TEST_F(VirtualSocketServerTest, tcp_send_v6) {
  TcpSendTest(kIPv6AnyAddress);
}

TEST_F(VirtualSocketServerTest, TcpSendsPacketsInOrder_v4) {
  TcpSendsPacketsInOrderTest(kIPv4AnyAddress);
}

TEST_F(VirtualSocketServerTest, TcpSendsPacketsInOrder_v6) {
  TcpSendsPacketsInOrderTest(kIPv6AnyAddress);
}

TEST_F(VirtualSocketServerTest, bandwidth_v4) {
  BandwidthTest(kIPv4AnyAddress);
}

TEST_F(VirtualSocketServerTest, bandwidth_v6) {
  BandwidthTest(kIPv6AnyAddress);
}

TEST_F(VirtualSocketServerTest, delay_v4) {
  DelayTest(kIPv4AnyAddress);
}

// See: https://code.google.com/p/webrtc/issues/detail?id=2409
TEST_F(VirtualSocketServerTest, DISABLED_delay_v6) {
  DelayTest(kIPv6AnyAddress);
}

// Works, receiving socket sees 127.0.0.2.
TEST_F(VirtualSocketServerTest, CanConnectFromMappedIPv6ToIPv4Any) {
  CrossFamilyConnectionTest(SocketAddress("::ffff:127.0.0.2", 0),
                            SocketAddress("0.0.0.0", 5000),
                            true);
}

// Fails.
TEST_F(VirtualSocketServerTest, CantConnectFromUnMappedIPv6ToIPv4Any) {
  CrossFamilyConnectionTest(SocketAddress("::2", 0),
                            SocketAddress("0.0.0.0", 5000),
                            false);
}

// Fails.
TEST_F(VirtualSocketServerTest, CantConnectFromUnMappedIPv6ToMappedIPv6) {
  CrossFamilyConnectionTest(SocketAddress("::2", 0),
                            SocketAddress("::ffff:127.0.0.1", 5000),
                            false);
}

// Works. receiving socket sees ::ffff:127.0.0.2.
TEST_F(VirtualSocketServerTest, CanConnectFromIPv4ToIPv6Any) {
  CrossFamilyConnectionTest(SocketAddress("127.0.0.2", 0),
                            SocketAddress("::", 5000),
                            true);
}

// Fails.
TEST_F(VirtualSocketServerTest, CantConnectFromIPv4ToUnMappedIPv6) {
  CrossFamilyConnectionTest(SocketAddress("127.0.0.2", 0),
                            SocketAddress("::1", 5000),
                            false);
}

// Works. Receiving socket sees ::ffff:127.0.0.1.
TEST_F(VirtualSocketServerTest, CanConnectFromIPv4ToMappedIPv6) {
  CrossFamilyConnectionTest(SocketAddress("127.0.0.1", 0),
                            SocketAddress("::ffff:127.0.0.2", 5000),
                            true);
}

// Works, receiving socket sees a result from GetNextIP.
TEST_F(VirtualSocketServerTest, CanConnectFromUnboundIPv6ToIPv4Any) {
  CrossFamilyConnectionTest(SocketAddress("::", 0),
                            SocketAddress("0.0.0.0", 5000),
                            true);
}

// Works, receiving socket sees whatever GetNextIP gave the client.
TEST_F(VirtualSocketServerTest, CanConnectFromUnboundIPv4ToIPv6Any) {
  CrossFamilyConnectionTest(SocketAddress("0.0.0.0", 0),
                            SocketAddress("::", 5000),
                            true);
}

TEST_F(VirtualSocketServerTest, CanSendDatagramFromUnboundIPv4ToIPv6Any) {
  CrossFamilyDatagramTest(SocketAddress("0.0.0.0", 0),
                          SocketAddress("::", 5000),
                          true);
}

TEST_F(VirtualSocketServerTest, CanSendDatagramFromMappedIPv6ToIPv4Any) {
  CrossFamilyDatagramTest(SocketAddress("::ffff:127.0.0.1", 0),
                          SocketAddress("0.0.0.0", 5000),
                          true);
}

TEST_F(VirtualSocketServerTest, CantSendDatagramFromUnMappedIPv6ToIPv4Any) {
  CrossFamilyDatagramTest(SocketAddress("::2", 0),
                          SocketAddress("0.0.0.0", 5000),
                          false);
}

TEST_F(VirtualSocketServerTest, CantSendDatagramFromUnMappedIPv6ToMappedIPv6) {
  CrossFamilyDatagramTest(SocketAddress("::2", 0),
                          SocketAddress("::ffff:127.0.0.1", 5000),
                          false);
}

TEST_F(VirtualSocketServerTest, CanSendDatagramFromIPv4ToIPv6Any) {
  CrossFamilyDatagramTest(SocketAddress("127.0.0.2", 0),
                          SocketAddress("::", 5000),
                          true);
}

TEST_F(VirtualSocketServerTest, CantSendDatagramFromIPv4ToUnMappedIPv6) {
  CrossFamilyDatagramTest(SocketAddress("127.0.0.2", 0),
                          SocketAddress("::1", 5000),
                          false);
}

TEST_F(VirtualSocketServerTest, CanSendDatagramFromIPv4ToMappedIPv6) {
  CrossFamilyDatagramTest(SocketAddress("127.0.0.1", 0),
                          SocketAddress("::ffff:127.0.0.2", 5000),
                          true);
}

TEST_F(VirtualSocketServerTest, CanSendDatagramFromUnboundIPv6ToIPv4Any) {
  CrossFamilyDatagramTest(SocketAddress("::", 0),
                          SocketAddress("0.0.0.0", 5000),
                          true);
}

TEST_F(VirtualSocketServerTest, SetSendingBlockedWithUdpSocket) {
  AsyncSocket* socket1 =
      ss_.CreateAsyncSocket(kIPv4AnyAddress.family(), SOCK_DGRAM);
  std::unique_ptr<AsyncSocket> socket2 =
      WrapUnique(ss_.CreateAsyncSocket(kIPv4AnyAddress.family(), SOCK_DGRAM));
  socket1->Bind(kIPv4AnyAddress);
  socket2->Bind(kIPv4AnyAddress);
  auto client1 = MakeUnique<TestClient>(MakeUnique<AsyncUDPSocket>(socket1));

  ss_.SetSendingBlocked(true);
  EXPECT_EQ(-1, client1->SendTo("foo", 3, socket2->GetLocalAddress()));
  EXPECT_TRUE(socket1->IsBlocking());
  EXPECT_EQ(0, client1->ready_to_send_count());

  ss_.SetSendingBlocked(false);
  EXPECT_EQ(1, client1->ready_to_send_count());
  EXPECT_EQ(3, client1->SendTo("foo", 3, socket2->GetLocalAddress()));
}

TEST_F(VirtualSocketServerTest, SetSendingBlockedWithTcpSocket) {
  constexpr size_t kBufferSize = 1024;
  ss_.set_send_buffer_capacity(kBufferSize);
  ss_.set_recv_buffer_capacity(kBufferSize);

  StreamSink sink;
  std::unique_ptr<AsyncSocket> socket1 =
      WrapUnique(ss_.CreateAsyncSocket(kIPv4AnyAddress.family(), SOCK_STREAM));
  std::unique_ptr<AsyncSocket> socket2 =
      WrapUnique(ss_.CreateAsyncSocket(kIPv4AnyAddress.family(), SOCK_STREAM));
  sink.Monitor(socket1.get());
  sink.Monitor(socket2.get());
  socket1->Bind(kIPv4AnyAddress);
  socket2->Bind(kIPv4AnyAddress);

  // Connect sockets.
  EXPECT_EQ(0, socket1->Connect(socket2->GetLocalAddress()));
  EXPECT_EQ(0, socket2->Connect(socket1->GetLocalAddress()));
  ss_.ProcessMessagesUntilIdle();

  char data[kBufferSize] = {};

  // First Send call will fill the send buffer but not send anything.
  ss_.SetSendingBlocked(true);
  EXPECT_EQ(static_cast<int>(kBufferSize), socket1->Send(data, kBufferSize));
  ss_.ProcessMessagesUntilIdle();
  EXPECT_FALSE(sink.Check(socket1.get(), SSE_WRITE));
  EXPECT_FALSE(sink.Check(socket2.get(), SSE_READ));
  EXPECT_FALSE(socket1->IsBlocking());

  // Since the send buffer is full, next Send will result in EWOULDBLOCK.
  EXPECT_EQ(-1, socket1->Send(data, kBufferSize));
  EXPECT_FALSE(sink.Check(socket1.get(), SSE_WRITE));
  EXPECT_FALSE(sink.Check(socket2.get(), SSE_READ));
  EXPECT_TRUE(socket1->IsBlocking());

  // When sending is unblocked, the buffered data should be sent and
  // SignalWriteEvent should fire.
  ss_.SetSendingBlocked(false);
  ss_.ProcessMessagesUntilIdle();
  EXPECT_TRUE(sink.Check(socket1.get(), SSE_WRITE));
  EXPECT_TRUE(sink.Check(socket2.get(), SSE_READ));
}

TEST_F(VirtualSocketServerTest, CreatesStandardDistribution) {
  const uint32_t kTestMean[] = {10, 100, 333, 1000};
  const double kTestDev[] = { 0.25, 0.1, 0.01 };
  // TODO(deadbeef): The current code only works for 1000 data points or more.
  const uint32_t kTestSamples[] = {/*10, 100,*/ 1000};
  for (size_t midx = 0; midx < arraysize(kTestMean); ++midx) {
    for (size_t didx = 0; didx < arraysize(kTestDev); ++didx) {
      for (size_t sidx = 0; sidx < arraysize(kTestSamples); ++sidx) {
        ASSERT_LT(0u, kTestSamples[sidx]);
        const uint32_t kStdDev =
            static_cast<uint32_t>(kTestDev[didx] * kTestMean[midx]);
        VirtualSocketServer::Function* f =
            VirtualSocketServer::CreateDistribution(kTestMean[midx],
                                                    kStdDev,
                                                    kTestSamples[sidx]);
        ASSERT_TRUE(nullptr != f);
        ASSERT_EQ(kTestSamples[sidx], f->size());
        double sum = 0;
        for (uint32_t i = 0; i < f->size(); ++i) {
          sum += (*f)[i].second;
        }
        const double mean = sum / f->size();
        double sum_sq_dev = 0;
        for (uint32_t i = 0; i < f->size(); ++i) {
          double dev = (*f)[i].second - mean;
          sum_sq_dev += dev * dev;
        }
        const double stddev = sqrt(sum_sq_dev / f->size());
        EXPECT_NEAR(kTestMean[midx], mean, 0.1 * kTestMean[midx])
          << "M=" << kTestMean[midx]
          << " SD=" << kStdDev
          << " N=" << kTestSamples[sidx];
        EXPECT_NEAR(kStdDev, stddev, 0.1 * kStdDev)
          << "M=" << kTestMean[midx]
          << " SD=" << kStdDev
          << " N=" << kTestSamples[sidx];
        delete f;
      }
    }
  }
}
